Bernie’s Bounding Box
Paddling Upstream Against the Transitive Dependency Cascade
The upstream fix is 10% of the problem. The other 90% is dead at the keyboard.
This week, Anthropic updated its coordinated vulnerability disclosure dashboard. The numbers should stop the industry in its tracks. A single frontier AI model — Mythos Preview — scanning roughly a thousand open-source projects has surfaced over 23,000 vulnerabilities. Of those, 6,200 are estimated high or critical severity. Human triage has managed to disclose 1,596 to maintainers so far. Ninety-seven have been patched. Six percent.
Anthropic’s own assessment: “Over 99% of the vulnerabilities we’ve found have not yet been patched.”
The AI security market has attracted billions in investment aimed at finding vulnerabilities faster and patching them faster. The finding part is working. The patching part — getting the fix from the root library through the dependency graph and into running applications — is not. And nobody building “AI-powered vulnerability management” is talking about why.
Twenty years as a developer and open-source maintainer living this graph — chasing library upgrades that cascaded across transitive dependencies, broke the build on evry try, and taught you to pin everything and touch nothing. Now I stare at the same graph from the other side, across thousands of production applications. The dead middle is not new. But the scale of coordination that’s now required to push continuous updates across tens of thousands of libraries and into production is... staggering.
A Patch Falls in the Dependency Forest
A vulnerability is discovered in zlib. You have never heard of zlib. It is a compression library embedded in virtually every networked application on earth — your web traffic, your APIs, your file transfers, your container images, the base layers of every Docker image your CI pipeline has pulled in the last three years. It has been maintained for decades, much of that time by a single person.
A patch ships. The patched version of zlib exists within days. Yay.
Your organization does not consume zlib directly. It runs Spring Boot, which depends on Netty, which depends on a native compression wrapper, which depends on zlib. It runs a Python analytics platform that uses pandas, which uses a C extension, which bundles a vendored copy of zlib inside a compiled wheel that was built on a maintainer’s laptop in 2022. It runs container images built on base layers pinned to a specific version from six months ago because the last infrastructure engineer who understood the Dockerfile left in Q3.
The patch exists. Your production environment does not have it. The maintainer of a middleware package that transitively depends on zlib through three layers of indirection does not know zlib was patched. If they do know, updating means running their test suite, validating nothing breaks, cutting a release, publishing it — for a vulnerability in a transitive dependency they did not choose and cannot see and would not recognize if you showed it to them. There is no commercial incentive. There is no contractual obligation. There is often no maintainer.
Merging onto an Abandoned Highway
Andrew Nesbitt spent the last several weeks asking the question nobody had bothered to quantify: how many of the open-source packages we all depend on are dead?
Not dormant. Not slow-to-respond. Dead. Issues filed, pull requests opened, but nobody with write access responding. He surveyed 5,874 critical repositories across sixteen package managers, using evidence of non-response rather than mere inactivity, deliberately undercounting rather than overcounting. The results draw the bounding box around every upstream remediation effort in the industry.
Forty-nine percent are unambiguously active. Twenty percent are dormant. Twelve percent are confirmed dead. Nineteen percent are unknown — nobody has filed an issue, so responsiveness has never been tested. The first security report against any of them will be that test. Over half of critical open-source infrastructure cannot confirm that anyone is home.
Those 713 confirmed-dead repositories back packages whose dependent-repo counts sum to roughly 290 million edges in the dependency graph. Add the dormant and unknown buckets and the number passes a billion. The most depended-upon dead packages are also the smallest — forty-line npm utilities with five million dependent repos and no maintainer activity in years. Very little to go wrong in forty lines. Also very little reason for anyone to ever read those forty lines again, which is simultaneously reassuring and the entire problem.
Nesbitt found 243 dead packages that had pull requests opened in the past year with zero merged. Some of those PRs are the security fix — the patch, written, reviewed, attached — sitting in an open pull request with nobody left who can press the button. The maintainer account that holds the publish rights on the registry has gone dark, lost its 2FA device, or forgotten the package exists. One thousand four hundred fourteen of the dead-or-dormant packages have exactly one account with publish rights, and for a lot of the dead ones it is reasonable to assume that account’s owner has moved on to goat farming or a startup or both.
This is the middle of the dependency graph. This is where patches go to die. Not because of malice, not because of incompetence, but because twelve percent of the critical infrastructure is dead at the keyboard and another thirty-nine percent is one career change away from joining it.
Logs, Regrets, and Lessons not Learned
Log4Shell proved this and the industry learned nothing from it.
A critical vulnerability in a Java logging library. Root fix shipped in days. The response was lauded as fast, coordinated, the model for how the ecosystem should work. Google’s Open Source Insights team measured the blast radius: over 17,000 Java artifacts affected — more than 4% of Maven Central — but only 3,500 of those depended on Log4j directly. The rest were transitive. Across the broader ecosystem, 200,000 package versions are directly named as vulnerable by known advisories, but nearly 15 million — 33% of the ecosystem — are affected indirectly through the dependency graph. Two orders of magnitude of amplification. The dependency graph does not just fail to propagate fixes. It amplifies exposure.
The depth data is worse. For more than 80% of affected packages, the vulnerability sat more than one level deep in the dependency graph — with a majority affected five levels down and some as many as nine. Each level is a separate maintainer who has to act before the fix can propagate further. And in the Java ecosystem, more than 99% of dependency requirements are “soft” — exact pinned versions that the resolution algorithm will not update automatically. Every hop requires explicit action. The algorithm will not help you.
The propagation timeline tells the rest. One week after disclosure, 13% of affected packages had remediated. Ten days, 25%. Six months later, roughly 40%. Then the curve flattened. Forty-nine percent of companies still carried Log4j in production two years later. Thirteen percent of all Log4j downloads in 2025 were still pulling the vulnerable version. Four years after the most publicized vulnerability in the history of software, with every scanner on the market flagging it, the fix could not cross the middle of the graph.
The natural question is why resolution algorithms don’t just prefer the latest patched version. The answer is that they tried, and it created a different disaster: npm’s open dependency ranges automatically propagated a malicious release of the colors package to over 50,000 dependent packages within hours. The ecosystem design choice that blocks fix propagation is the same one that prevents malicious propagation. There is no free lunch — which is precisely why rebuilding from source and patch-in-place backporting exist as structural alternatives to waiting for the resolution algorithm to save you.
A sophisticated counterargument: this varies by ecosystem. In npm, Python, and Rust, intermediate packages typically declare version ranges rather than exact pins — meaning the resolver can technically pick up a patched root version without the middle of the graph releasing anything new. But the fix only resolves when the consuming application regenerates its lockfile — the file that pins every transitive dependency to the exact version resolved at build time. Standard CI practice is --frozen-lockfile, not re-resolve. And in the Java ecosystem — where the enterprise dependency graph is deepest and the propagation failure most measured — 99% of dependencies use exact version specifications the resolver will not update automatically. The bottleneck shifts from the middle of the graph to the consumer’s lockfile in some ecosystems. In others, the middle remains the hard stop. In both, someone must act.
The graph has not solved the propagation mechanics for even one Log4Shell. Now: frontier AI models are surfacing vulnerabilities across the open-source substrate simultaneously. A large enterprise consumes 35,000 open-source libraries directly — before you count the transitive graph. Each one of those libraries is a potential propagation problem through the same dead and dormant middle that could not deliver one universally known fix in two years. AI increases the number of fixes that must traverse that graph. It does not widen the graph’s capacity to deliver them.
Go look. Run mvn dependency:tree or npm ls --all against any production application. Count the transitive dependencies your team has never evaluated, approved, or heard of. Then open deps.dev and check which of them have open advisories with no patched version. What you find in the middle will not be reassuring.
Patch Faster, Fund Maintainers, or Bypass the Middle
The industry’s response falls into three camps, and the structural failure lives in the gap between them.
The first camp says patch faster. This is the largest camp by headcount, investment, and confidence — the analyst firms calling for compressed patch timelines, the managed security providers standing up AI tiger teams, and the auto-remediation startups raising money at a pace that suggests the problem is venture-solvable. Cogent Security raised $42 million to build AI agents that chase down system owners and write remediation tickets. Astelia raised $35 million. Reclaim raised $20 million. Onit raised $11 million. Over $100 million into the organizational coordination layer — the workflow between “scanner found it” and “engineer fixed it.” Every one of these vendors assumes the fix reaches the application. None of them addresses what happens when the fix reaches a package in the middle of the graph and the maintainer is dead at the keyboard.
The second camp says fund the maintainers. This is OpenSSF, Alpha-Omega, the $12.5 million from Anthropic, AWS, Google, Microsoft, and OpenAI directed at helping open-source projects handle the surge of AI-generated vulnerability reports. Necessary work at the top of the pyramid — the critical projects with known maintainers who need tooling, funding, and protection from the deluge of AI-generated slop reports that is making solo maintainership steadily less appealing as a way to spend your evenings. But the dependency graph problem is not about the projects with maintainers. It is about the long tail — the thing someone wrote on a Tuesday that became an OSS blockbuster and a critical dependency across a thousand commercial projects, maintained by a single account that last pushed a commit when Obama was president. HeroDevs estimates 81,000 open-source package versions with known CVEs that are end-of-life and unpatchable — no fix coming, maintainer gone, release line closed — and believes the real number is closer to 400,000. You cannot fund your way to a fix when there is nobody to receive the check. The logical endpoint of “support the ecosystem” at the scale the dependency graph requires is adopting all of open source and running a planet-scale pet shelter. Noble. Structurally impossible.
The third camp — the smallest and least funded — says bypass the middle entirely. The approach takes two forms. Rebuild-from-source pipelines — Chainguard is the most visible — rebuild libraries from verified source code across Java, Python, and JavaScript, so that when a root dependency ships a security fix, the entire downstream graph gets rebuilt with the patched version. No intermediate maintainer required, no PR sitting unmerged, no publish account gone dark. Patch-in-place and backporting services — Seal Security, HeroDevs, ActiveState — backport security fixes into the specific versions applications actually consume, including transitive, shaded, and end-of-life dependencies, so organizations can remediate without the forced upgrade that breaks everything downstream. Both approaches route around the dead middle of the graph rather than waiting for it to act. Both are growing. Neither is the thing the industry is spending its hundred million dollars on.
There is an optimistic counterargument, and it deserves honest engagement. In six months, capable AI models will be available to every maintainer. The ones who care will build their own test harnesses, scan their own code, understand their own context better than any external scanner, and patch fast. That is probably true, and it will be the new normal for maintained projects. But the dependency graph problem is not about the maintainers who care. It is about the packages where nobody is home — the twelve percent confirmed dead, the twenty percent dormant, the nineteen percent untested. AI makes the willing faster. It does not create willingness where there is none, and it does not resurrect the dead.
Crashing Overrides
There is also a longer-arc response taking shape — the push toward memory-safe languages, CISA’s guidance, the White House ONCD report, Google’s incremental Rust migration. This is the right structural direction. It also operates on a timescale measured in decades, does nothing for the existing graph, and does not address the propagation problem for the non-memory-safety vulnerabilities that constitute the majority of the current backlog.
None of this is an excuse for consumers. Enterprises are not passive victims of the dependency graph. They choose stale base images, tolerate old lockfiles, approve one-off libraries, ignore end-of-life signals, and treat SBOMs as compliance paperwork rather than operational infrastructure. Dependency override mechanisms exist in every major ecosystem — Maven dependency management, npm overrides, Go replace directives. And for the growing class of packages that ship as compiled binaries — shaded JARs in Java, native extensions in Python, bundled artifacts in JavaScript — the resolver never touches the vulnerability at all. It lives inside a compiled artifact the build system cannot inspect or override. The fix requires the upstream maintainer to rebuild the binary against patched native dependencies, and the consumer to pull the rebuilt artifact. One more human action in a chain already saturated with them.
The controls exist. Individually, each one works. The institutional capability to orchestrate them does not. An enterprise with thousands of distinct build units, tens of thousands of dependency versions, and hundreds of thousands of patch propagation chains cannot push dependency graph remediation to application teams that struggle to fix SAST, SCA, and vulnerability management scan results in a timely manner under normal conditions. The mechanisms are available at the individual application and individual package level. Coordinating them across the estate of a large enterprise — with the heterogeneity native to decades of acquisitions, platform migrations, and organic growth — is an organizational problem that no dependency override command resolves.
And not every stranded fix is equally urgent. Presence is not exploitability. A vulnerable transitive package may be unreachable, disabled, or mitigated at runtime. But exploitability does not solve propagation — it only prioritizes it. The structural issue remains: when a fix matters, the graph has no guaranteed path to deliver it.
The answer is all three camps simultaneously — and the honest admission that even all three together draw a box around the problem that is considerably smaller than the problem itself.
Upstream remediation is necessary. The root fix has to exist. Rebuild-from-source is necessary. Something has to bypass the middle of the graph for the ecosystems it covers. Institutional consumption enforcement is necessary — SBOM visibility, dependency graph resolution, policy that refuses to deploy software with known vulnerable transitive dependencies. But for every library that gets rebuilt from source, there are packages outside the coverage of any rebuild pipeline — the Go binary vendored inside a container that was never built from a reproducible manifest, the npm utility with five million dependents and no buildable source because the maintainer’s build toolchain is a shell script on a laptop that no longer exists, the internal fork of a framework last updated when the developer who understood it left for a startup in 2019. For every institution that enforces dependency policy at the consumption layer, there are applications whose dependency graphs cannot be fully resolved — Python’s resolver is non-deterministic, npm’s is tree-duplicating, and the enterprise that claims complete SBOM coverage of its transitive dependency tree is the enterprise that has not actually tried. For every maintainer that Alpha-Omega funds, there are a thousand packages in the long tail that no funding program will ever reach, because nobody knows they matter until the day they do.
Bernie’s Bounding Box
Five to fifteen percent of components in enterprise dependency graphs are end-of-life, even in organizations with mature security programs. That number shows up consistently, across ecosystems, and persists because it is structural — not a hygiene failure. Teams govern their direct dependencies carefully and still find end-of-life exposure in the transitive layer, because the transitive layer is not theirs to govern.
Bernie’s Bounding Box is the hard structural ceiling on vulnerability remediation effectiveness imposed by dead, dormant, and abandoned packages in the transitive dependency graph. No matter how fast you discover, how fast you patch at the root, how much you spend on ecosystem maintenance — if a Bernie sits between the fix and your running application, the patch stops there. The PR is open. The code is written. The publish account is dark. The bounding box is drawn by the Bernies, and over half of critical open-source infrastructure cannot confirm that anyone is home.
The upstream fix is necessary. It is ten percent of the problem. The other ninety percent is dead at the keyboard.
The Disclosure Dilemma
There is a darker implication that the industry has not yet confronted, and it changes the calculus on everything above.
The traditional model of vulnerability disclosure assumes a temporary exposure window: vulnerability is disclosed, defenders patch, the window closes. The entire framework of responsible disclosure, coordinated embargo, and remediation SLAs is built on that assumption. The window is uncomfortable but finite. The fix propagates. The exposure ends.
Dead nodes break that assumption. When a vulnerability is disclosed in a root library, the disclosure simultaneously publishes a map of every transitive path where the fix will never arrive. The dead intermediate package will not consume the patched version — not eventually, not slowly, not after a funding grant. Never. The maintainer is gone. The publish account is dark. The PR with the fix will sit unmerged until the registry sunsets or the heat death of the universe, whichever comes first. For every path through the dependency graph that passes through a dead node, the disclosure does not create a temporary window. It creates a permanent one. And that window is visible to anyone with access to the dependency graph — which, thanks to deps.dev, is everyone. The targeting workflow is deterministic: a disclosed CVE, a public dependency graph database, a maintainer health check, and a list of permanently exploitable paths. No zero-day required.
This would be a manageable concern at the current rate of disclosure. The NVD publishes roughly 25,000 CVEs per year. But AI-powered vulnerability discovery is about to change the denominator. Multiple frontier AI programs — not just one — are scanning open-source libraries at computational speed, producing findings at a rate that will rival and then dwarf the NVD’s annual output. Each finding that reaches public disclosure creates permanent targeting paths through every dead node in its transitive graph. The exposure scales linearly with disclosure volume. At 25,000 CVEs a year, permanent targeting through dead nodes is background noise. At the volumes AI-driven discovery is approaching, it becomes the dominant new source of durable, structurally guaranteed attack surface.
There is an information asymmetry here that the disclosure model has not grappled with. AI-driven discovery is producing findings that adversaries likely cannot replicate independently at comparable scale or speed. Every disclosure through a dead node transfers that asymmetry permanently.
And there is a circularity that no disclosure timing model resolves cleanly. Ninety percent of commercial software is built on open source. The same libraries the scanning programs find vulnerable are bundled inside vendor products — the EHR platform at the hospital, the SCADA firmware at the utility, the transfer agency system at the bank, the POS software at the retailer. Those vendors cannot patch what they do not know about. If disclosure is held to allow rebuild propagation, the vendor remains blind. If disclosure goes public to enable the vendor, the dead nodes create permanent targeting. Both choices impose permanent consequences on someone. Neither can be deferred. The dependency graph does not just create a remediation problem. It creates a disclosure problem that the industry’s existing coordination models were not designed to handle and cannot resolve without structural reform.
There is exactly one mechanism that bypasses the dead middle: rebuilding the dependency graph from patched sources, so that the fix is present at every layer without waiting for the middle to act. That infrastructure is not just a remediation convenience. It is a prerequisite for safe disclosure — and it must exist before the volume arrives, not after.
Board Here for Panic
The next time someone presents an AI-powered vulnerability management solution, ask three questions.
First: when we patch a library, how does the patch reach our running applications through the dependency graph? If the answer depends on the cooperation of maintainers who have no obligation to cooperate and may not exist, that is not a plan. It is a hope.
Second: when we disclose a vulnerability, what permanent attack surface does the disclosure create through dead nodes in the dependency graph? If nobody in the room can answer that question, you are publishing targeting maps you have not read.
Third: how many of our vendor products bundle the same open-source libraries we have already patched in our own environment — and what happens to those vendors when we disclose?
Until someone solves the middle of the graph, the patch is not the fix. Until the rebuild infrastructure exists at scale, disclosure is a weapon pointed in the wrong direction. And until the vendor supply chain can act on pre-disclosure findings, non-disclosure is a shield with a hole in it.
This is the second in a series on the structural failures in vulnerability management that technology alone does not solve. The first, Off the Beaten Patch, argued that discovery is not the bottleneck — remediation is. This piece argues that even remediation at the root is insufficient when the dependency graph has no mechanism to propagate fixes to production — and that the act of disclosure itself may create permanent damage through the dead middle of the graph. The third — The One-Armed Zero-Day Bandit — will address the convergence problem in AI-powered vulnerability scanning.




