node_modules/.package-lock.json is the hidden lockfile npm writes since v7. It records the tree as installed so npm can skip reading every folder in node_modules. It is a performance cache, not a security control, and npm ignores it when the folder contents or timestamps do not match.
What it is
The npm docs describe it as a hidden lockfile that lets npm avoid processing the whole node_modules folder repeatedly. It contains information about the installed tree. It is lockfileVersion 3, and it lacks the backward compatibility data that a normal package-lock.json can carry.
Do not confuse it with your committed package-lock.json. That file describes the tree you want everyone to install. The hidden one describes what is on this disk right now.
When npm uses it
According to the docs, npm uses the hidden lockfile instead of reading the full hierarchy only if all three conditions hold:
- Every package folder it references exists in node_modules.
- No package folder exists in node_modules that is not listed in it.
- The modified time of the file is at least as recent as all the package folders it references.
In plain terms, it is relevant only if it was written during the most recent update to the tree. If another tool changes the tree, npm detects that and ignores it.
The caveat that matters for security
The docs are direct: it is possible to change the contents of a package in a way that leaves the folder's modified time untouched. If you add a file at node_modules/foo/lib/bar.js, the modified time of node_modules/foo does not change. The hidden lockfile cannot see that edit.
So the hidden lockfile does not verify file contents. Anyone or anything that can write inside node_modules can alter code without npm noticing through this mechanism. The docs' advice for people who edit files in node_modules by hand is to delete the hidden lockfile.
| Question | Answer |
|---|---|
| Is it committed to git | No, it lives inside node_modules |
| Does it verify file contents | No |
| Does it describe the desired tree | No, the committed lockfile does |
| Is it safe to delete | Yes, npm rebuilds it |
Practical advice
- Never treat node_modules as a trusted artifact. In CI, start clean. npm ci removes an existing node_modules folder before it installs, according to its docs, and installs from the committed lockfile.
- If you cache node_modules between runs, understand who can write to the cache. Our post on pnpm store cache in CI covers the same question for another manager.
- When debugging odd behavior after patching a package in place, delete node_modules/.package-lock.json so npm re-reads the folders.
- For scanning, point tools at the committed lockfile or the built artifact, not at the hidden file. See lockfile or manifest for build-time scans.
A quick audit
To compare disk with intent, install cleanly from the lockfile in a scratch directory and diff the resulting trees, or run the audit signatures command after an install to check registry signatures for what was installed.
Where Safeguard fits
Safeguard's dependency scanning and SBOM generation work from the committed lockfile and the artifacts you build, not from a cache on a developer disk, so the inventory reflects what you intend to ship. A free scan is at https://gold.safeguard.sh/scan.
Quick check
Should I commit node_modules/.package-lock.json?
No. It lives inside node_modules, is a local cache, and npm rebuilds it. Commit package-lock.json at the project root.
Can it detect a file edited inside node_modules?
Not reliably. The npm docs say a content change can leave the folder modified time unchanged, so the hidden lockfile will not notice.
Sources
Last reviewed: 19 October 2026.