They can, if the scan reads lock files. A transitive dependency is a package your dependencies depend on, and it appears with exact versions only in the resolved tree. A pull request scan that reads only the manifest sees direct dependencies and misses most of what actually ships.
Definition
A direct dependency is one you list yourself. A transitive (or indirect) dependency is one pulled in by something you listed. Chains can be several levels deep, so a project with a modest manifest can resolve to a large tree.
What the evidence says
GitHub's dependency review documentation says the review includes details of changes to indirect dependencies in lock files. It also warns that if an updated direct dependency has updated dependencies of its own, the pull request may contain more changes than you expected. In other words, the transitive part is where surprises hide, and the lock file is where the tool finds it.
When a pull request scan will miss transitive packages
| Situation | Result |
|---|---|
| Manifest changed, lock file not committed | Only direct changes visible |
| Lock file regenerated in CI, not in the pull request | The scan reads the old tree |
| Lock file changed but scanner ignores it | Transitive changes invisible |
| Ecosystem without lock file convention | Needs a resolved tree produced in CI |
| Vendored or bundled code | Not seen as dependencies at all |
How to make transitive coverage real
- Commit lock files so every change to the tree shows up in the diff.
- Check that your scanner lists transitive packages. Run it on a known project and compare the count with the lock file.
- Fail the pull request if the lock file is out of date relative to the manifest, as npm's clean install does by erroring on a mismatch.
- For ecosystems that lack lock files, generate a resolved tree in CI and scan that.
- Add a scheduled full scan, since new advisories often land on transitive packages nobody chose.
Why transitive findings need extra care
You did not pick these packages, so the fix is not always in your hands. The options, in order:
- Upgrade the direct dependency that pulls it in, if a newer one fixes it.
- Use your package manager's override or resolution feature to force a patched version, and test.
- Check reachability. If the vulnerable code is not called, record that and schedule the fix.
- If there is no fix, add a compensating control and an owner.
Reachability matters more here than anywhere, because most transitive packages are used in small ways.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how many packages sit below the ones a developer chose.
Where Safeguard fits
Safeguard scans direct and transitive dependencies, generates SBOMs, and offers reachability analysis to show which findings your code can actually reach. Run a free scan at gold.safeguard.sh/scan.
Quick check
Is a lock file always needed for transitive coverage?
Not strictly, but without a resolved tree your scan has to guess versions. A committed lock file is the simplest reliable input.
Who fixes a vulnerable transitive package?
Usually you, by upgrading the parent package or overriding the version, unless the maintainer of the parent ships a fix first.
Sources
- GitHub Docs, About dependency review
- npm Docs, npm ci
Last reviewed: 19 October 2026.