Approve direct dependencies by name and an owner, and govern transitive ones with rules instead of individual sign-off: scan every resolved package, enforce license and source policy, and flag growth. Approving each transitive package by hand does not scale and leads to rubber-stamping.
The problem in plain terms
A direct dependency is one your code names. A transitive dependency is one that a direct dependency pulls in, and the dependencies of those, and so on. A small manifest can resolve to a very large tree, and the tree changes whenever an upstream package changes its own requirements.
An approved list that only holds direct names is incomplete, and one that tries to hold everything goes stale within days.
A two-level model
| Level | How it is governed | Who decides |
|---|---|---|
| Direct | Named on the approved list with an owner and a reason | A person, through intake |
| Transitive | Automatic rules on every build | Policy, with exceptions by a person |
The owner of a direct dependency answers for what it brings in. If a direct package keeps pulling in troublesome transitive ones, the owner decides whether to replace it.
Rules for the transitive layer
- Everything resolves through the mirror. No transitive package should come from anywhere else.
- Every resolved package is scanned. The SBOM is generated from the lockfile, not the manifest, so the scan sees the whole tree.
- Block on policy, not on names. Block known malicious packages, disallowed licenses and critical advisories where a fix exists.
- Watch growth. A new direct dependency that adds many transitive packages gets a human look.
- Watch for new install scripts. A transitive package that runs code at install time is a different kind of risk from a pure library.
What to do about a bad transitive package
You usually cannot edit the package. Your options, from least to most invasive:
- Upgrade the direct dependency to a version that no longer pulls it in.
- Use the package manager's override or resolution feature to pin a safe version, and record why.
- Replace the direct dependency.
- Block the transitive package at the mirror, and accept that the build for that dependency will fail until fixed.
Write the override down with an owner and a review date. Forgotten overrides become their own supply chain problem.
Reachability helps you prioritise
Not every vulnerable transitive package is actually called by your code. Reachability analysis checks whether your application can reach the vulnerable function, which helps you decide what to fix first. It does not replace policy, and a malicious package should be blocked whether or not it is reached.
Try it yourself
Click through it at your own pace, or open it full screen.
Watch how many findings sit in code paths the application never calls, and how that changes the order of work.
Where Safeguard fits
Safeguard offers SBOM and dependency scanning across the full tree and reachability analysis to rank findings. You can see the output on your own code with the free scan.
Quick check
Should transitive packages appear on the approved list?
Usually not by name. Keep them visible in the SBOM and governed by policy, with exceptions recorded when needed.
Who owns a transitive dependency problem?
The owner of the direct dependency that brought it in.
Last reviewed: 19 October 2026.