Understanding the Dependency Graph
When you add a library to your project, that library has its own dependencies (its "direct" dependencies from your perspective are its "transitive" dependencies from yours). Those packages have dependencies too. The result is a directed graph that can be several levels deep, with hundreds or thousands of nodes representing packages you never made a conscious decision to include.
Most developers are only aware of their direct dependencies — the ones listed in their package.json, requirements.txt, pom.xml, or go.mod. The transitive graph is typically only visible by running a command like npm ls or mvn dependency:tree, and even then it can be overwhelming to parse manually.
Why Transitive Risk Is Harder to Manage
When a vulnerability is found in a direct dependency, the fix path is usually clear: update the package. When a vulnerability is found in a transitive dependency, the remediation is more complex. You cannot directly update a package you do not declare — you must update the direct dependency that pulls in the vulnerable transitive package, and only if a version of that direct dependency exists that uses a patched version of the transitive package. Sometimes no such version exists yet, and your only options are waiting for an upstream fix or forking and patching yourself.
This complexity is why approximately 30% of organizations report that their vulnerability backlog contains issues they cannot resolve because a fix does not exist upstream yet. Transitive dependency chains create vulnerability exposure that is partially outside your control.
License Risk in the Transitive Graph
License risk follows the same pattern. The GPL or AGPL library that creates legal exposure for your product is rarely a direct dependency — it is typically buried two or three levels deep. One copyleft library in your transitive graph carries the same legal weight as a direct copyleft dependency, but it is exponentially harder to discover without automated tooling.
The Orange S.A. case — where a large telecom paid over €900,000 for using a GPL library — began with exactly this kind of indirect dependency. Engineers chose libraries that seemed fine. They did not audit those libraries' own dependencies for license compliance. The exposure accumulated silently for years before becoming a legal liability.
Practical Steps for Transitive Risk Management
First, use a lock file. Lock files (package-lock.json, Pipfile.lock, yarn.lock) pin all transitive dependencies to exact versions, making the full dependency graph deterministic and scannable. Second, use an SCA tool that analyzes the complete dependency graph, not just direct dependencies — many simpler tools only scan the first level. Third, generate and maintain an SBOM that captures the full dependency graph, so you have an authoritative record of everything in your application.
See Your Full Dependency Tree with Fossity
Fossity — Fossity analyzes your complete dependency graph — direct and transitive, across all ecosystems — and surfaces vulnerability and license risk at every level. Stop flying blind on what is actually running in your software.
Visit Fossity.com →