Most of the code running in your product was written by people you've never met, in packages you never chose. You picked a dozen libraries; those libraries picked hundreds more. That invisible tail is where nearly all of your open-source risk actually lives, and two famous incidents showed exactly how much damage it can do.
Key Takeaways
- Roughly 95% of open-source vulnerabilities sit in transitive dependencies rather than the ones you chose (transitive dependency risk).
- Twelve direct dependencies can pull in hundreds of packages in total (managing dependencies).
- Log4Shell spread because Log4j was pulled in indirectly by frameworks, not declared directly.
- left-pad (11 lines) broke large parts of the web in 2016 when its author removed it.
The Tail You Didn't Choose
When you add a package, you inherit its dependencies, and theirs, and so on. The numbers get out of hand fast: a project with twelve direct dependencies can end up installing hundreds of packages once the transitive tree resolves (OpenSSF). You reviewed twelve. You're running hundreds.
That's where the risk concentrates. Analyses of open-source vulnerabilities find roughly 95% of them live in transitive dependencies rather than in the packages teams actually chose and declared (the transitive blind spot). Your security review looked at the packages you chose. The vulnerabilities were mostly somewhere else.
| What you see | What you actually run |
|---|---|
| ~12 direct dependencies | Hundreds of packages |
| The libraries you reviewed | Their dependencies, unreviewed |
| ~5% of vulnerabilities | ~95%, in the transitive tail |
Two Incidents That Made It Concrete
Log4Shell (2021). The Log4j vulnerability became the textbook case precisely because almost nobody declared Log4j directly. It arrived transitively, pulled in by Spring Boot, Struts, and dozens of other frameworks (why transitive dependencies matter). Teams spent frantic days just answering "do we even use this?", because the answer lived several levels deep in a dependency tree nobody had mapped.
left-pad (2016). A developer removed his packages from npm, including left-pad, eleven lines of code that padded a string. Builds broke across a startling share of the web, because so much infrastructure depended on it indirectly (the left-pad cascade). Nobody chose left-pad. Everybody had it.
A Concrete Version
A team gets a critical CVE alert on a Friday. The vulnerable package appears nowhere in their dependency manifest, so the first hour goes to figuring out whether they're even affected. They are: it's four levels deep, pulled in by a build tool's plugin's helper library. The fix requires upgrading a direct dependency that has breaking changes, so a "just patch it" task turns into a two-day migration. None of that time went to the vulnerability itself. It went to discovering a dependency tree nobody had ever looked at.
What Actually Helps
The practical defenses are unglamorous. Generate a software bill of materials so you can answer "do we use X?" in seconds instead of hours. Run automated dependency scanning that covers transitive packages, since scanning only direct ones misses where the risk lives. Keep dependencies current, because the upgrade you postpone for a year becomes the emergency migration during an incident. And be genuinely reluctant to add packages: every dependency is a permanent commitment, which is another argument for choosing boring, well-maintained technology with real maintainer communities behind it.
The Honest Counterpoint
The answer to dependency risk is not to write everything yourself. Reimplementing crypto, parsers, or HTTP clients in-house is usually far more dangerous than depending on a battle-tested library that thousands of people have reviewed, and the productivity loss would be enormous. Open source is a spectacular deal; the risk is the price of it. The goal is informed dependency use: know what you're running, scan the whole tree, prefer well-maintained packages with real communities, and avoid pulling in a hundred transitive packages to save yourself ten lines.
What This Means for Teams
Dependency hygiene is the kind of foundational discipline that only shows up when it's missing, usually at 2am during a CVE scramble. Engineers who've lived through a Log4Shell-style incident set up SBOMs, scanning, and upgrade cadences early, the same instinct behind observability and security basics for startups: invest before the incident proves why it mattered. See available engineers.
Frequently Asked Questions
Where do most open-source vulnerabilities come from?
Analyses find roughly 95% live in transitive dependencies, the packages your dependencies pull in, rather than the ones you selected directly. Scanning only direct dependencies misses most of the risk.
How many packages am I actually running?
Far more than you chose. A project with about twelve direct dependencies can resolve into hundreds of packages once the transitive tree installs.
What made Log4Shell so hard to respond to?
Log4j was rarely a direct dependency. It arrived transitively through frameworks like Spring Boot and Struts, so teams first had to determine whether they were even affected, several levels deep in an unmapped tree.
Should we just write more code ourselves?
Usually no. Reimplementing crypto, parsers, or HTTP clients is typically riskier than using battle-tested libraries. Aim for informed use: SBOMs, full-tree scanning, current versions, and reluctance to add packages casually.
The Bottom Line
You chose a dozen libraries and inherited hundreds, and about 95% of your open-source vulnerability exposure lives in that tail you never reviewed. Log4Shell and left-pad both spread through it. Map what you actually run, scan the whole tree, keep versions current, and treat every new dependency as the permanent commitment it is.
Roberto Espinoza is CEO of Ruzora, which helps US startups hire pre-vetted senior LATAM engineers in 72 hours. See available engineers.
