A scanner can judge the version range in your manifest or the exact version pinned in your lockfile. If it reads only the manifest, a range like a caret can look vulnerable even when the lockfile installs a patched release. Check which file the scanner used before you call a finding a false positive.
Two files, two answers
A manifest, such as package.json, states what you accept: a range. A lockfile states what you got: an exact version. The npm documentation says the lockfile exists so that later installs produce identical trees regardless of intermediate dependency updates. That makes it the best record of what actually ships.
If a scanner reads only the manifest, it has to guess. Some pick the lowest version in the range, which can be old and vulnerable. Some pick the highest. Neither is what you deployed.
How the mismatch shows up
- A finding names version 1.2.0, but your lockfile says 1.4.3.
- A finding disappears after you commit the lockfile.
- Two scanners disagree and one of them did not find a lockfile.
- A monorepo package has a manifest but its lockfile lives at the repository root.
A five step check
- Read the finding. Note the package and the version it reports.
- Find the resolved version. In your lockfile, search for the package name. In a project with several lockfiles, check each one.
- Compare. If they match, the finding stands. If not, the scanner used the wrong source.
- Look at the scanner setup: does it point at the lockfile, the manifest, or an installed tree? Fix the configuration rather than suppressing.
- Rescan. The finding should now match reality.
| Scanner input | What it can tell you | Weak point |
|---|---|---|
| Manifest only | Direct dependencies and ranges | Cannot know the resolved version |
| Lockfile | Exact versions, including transitive | Stale if not committed after changes |
| Installed tree or built artifact | What is truly present | Needs a build step |
Why not just suppress it
A suppression hides the symptom. If the scanner keeps reading the manifest, every new advisory will produce the same noise, and a real vulnerable version could hide among it. Fixing the input is a one time job.
The reverse is also true: a clean scan on the manifest alone can miss a vulnerable transitive version pinned in the lockfile. Our post on lockfiles for apps and libraries explains when to commit each.
Libraries are different
A published library ships a range, because its consumers resolve their own tree. For a library, what the consumer resolves matters more than your own lockfile. Scan both: your lockfile for your tests and build, and a fresh install for what a new consumer would get.
Try it yourself
Click through it at your own pace, or open it full screen. Look at the resolved versions in the inventory and compare them with what a range alone would suggest.
Quick check
Should I commit the lockfile so scans are accurate?
For applications, yes. It gives scanners exact versions. For libraries, scan a fresh install as well.
Why do two scanners report different versions?
One may read the manifest and the other the lockfile or installed tree. Compare their inputs first.
Sources
Last reviewed: 19 October 2026.