how to audit transitive dependencies for vulns
Audits transitive dependencies for known vulnerabilities: resolves the full dependency tree from the lockfile, scans every layer including dependencies-of-dependencies, and triages the findings by reachability. Use when direct dependencies look clean but the tree is deep, before a release, or after a CVE in a popular transitive library. Not for license auditing, not for your own code.
TL;DR
Your direct dependencies are the tip of the tree. The real risk lives three layers down where libraries you never chose get pulled in silently. Resolve the full tree from the lockfile, scan every layer, and triage by whether the vulnerable code is reachable from your app.
how to audit transitive dependencies for vulnsUse this when
- Your direct dependencies are clean but the dependency tree is deep
- A CVE drops in a library you dont directly depend on
- Before a release, as a supply-chain sanity check
- You inherited a project and nobody knows what is really in the tree
Not for
- Auditing your own first-party code
- License compliance of the tree (related, different goal)
- Runtime behavior analysis of dependencies
Steps
1. Resolve the full tree from the lockfile.
Use your package managers tree command against the lockfile to list every transitive dependency with its resolved version. The lockfile is the truth, the manifest is a wish.
Expected: a complete flattened list of package plus version for the whole tree.
2. Scan the whole tree, not just the top layer.
Run your vulnerability scanner against the lockfile so it evaluates transitive packages too. Confirm the scanner is configured to include transitive deps, some default to direct-only.
Expected: findings that include packages you never directly added.
3. Map each finding to its root.
For every flagged transitive package, trace which direct dependency pulls it in. Fixing happens at the root, not at the leaf.
Expected: each alert annotated with the root package responsible for it.
4. Triage by reachability.
Check whether your app actually exercises the vulnerable code path. A vulnerable function in a transitive dep that your code never calls is low priority. One on your hot path is not.
Expected: findings split into reachable and unreachable, with evidence noted.
5. Fix at the root.
Upgrade the root dependency to a version that pulls the fixed transitive version, or add an explicit override or resolution forcing the patched version. Verify the tree resolves clean after.
Expected: the tree re-resolves with the vulnerable version gone.
6. Lock it in.
Commit the updated lockfile and add the scan to CI so the tree cant silently regress. Future dependency adds get scanned before merge.
Expected: CI fails on new vulnerable transitive deps.
Variant phrasings
How to find vulnerabilities in dependencies of dependencies
Resolve the full tree from the lockfile and scan it with transitive coverage enabled. Thats the whole technique.
Scanner only checks direct dependencies
Reconfigure it to read the lockfile. If your scanner cant do transitive, switch scanners, because direct-only is theater.
How to fix a CVE in a transitive dependency
Upgrade the root package that pulls it in, or force the patched version with an override. Never hand-edit the lockfile entry for the leaf alone.
Why it happens
Package managers resolve transitive dependencies automatically and silently, so your tree grows without anyone choosing those packages. Vulnerability databases track every package version, but scanners that only read your manifest never see the transitive layers. The gap between what you chose and what you ship is where these CVEs hide.
Edge cases
- Diamond dependencies with conflicting versions: two roots pull different versions of the same transitive package. The resolver picks one, and the losing version might be the vulnerable one. Check the resolved version, not the requested ones.
- No fixed version at the root: if no root upgrade pulls the fix, force the patched transitive version with an override and test. Overrides can break the root, so test the feature that uses it.
- Huge tree, hundreds of findings: triage reachable first, then batch the rest into root upgrades. Dont try to fix leaves one by one.
- Lockfile out of sync with the manifest: regenerate the lockfile before the audit. An audit against a stale lockfile audits a tree you dont actually ship.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstxtifKfMMl-St4aRmeBvUQ