The dependency that stayed quiet for nineteen weeks
The advisory landed on a Tuesday in March, but the vulnerable version had been in the dependency tree since November. It was a transitive dependency, three levels down, pulled in by a logging library that almost nobody on the team had reason to open. Nineteen weeks. In that window there were four security audits, two of them explicitly scoped to include third-party packages. Each one passed. The commit stream showed steady, competent work. The CI results were green. The incident feed was quiet. Every stream a team could reasonably watch was saying the system was fine, and the system was not fine.
The staff engineer who owned the audit process had, by any reasonable account, done the job. He had a checklist. He ran `npm audit` and its equivalents, cross-referenced known-CVE lists, and signed off. What he did not do — what none of the four audits did — was pull the full dependency graph fresh each time and diff it against the previous one. He re-ran the same query against the same slice of the tree he had checked before, because that slice had a history of being clean and the new top-level dependencies looked routine. The transitive package four levels down was never queried directly, because nothing in the last three audits had ever surfaced a problem there, and a clean history is exactly the kind of evidence that makes an inquirer stop looking in a particular place.
What actually went wrong
This is not a story about carelessness. The audits were real, logged, and defensible in a post-incident review taken at face value. What went wrong sat earlier than any of that, at the point where the staff engineer decided which query to run. He asked, in effect, "does this look like the last three audits, which were fine?" rather than "what has changed in this tree since I last looked, all the way down?" The first question samples for agreement with a prior belief — the dependency tree is healthy — and the second samples for whatever might contradict it. Both questions are legitimate audit procedures. Only one of them can catch a silent regression buried in a package nobody actively watches.
The vulnerability advisory, when it finally came, arrived through a different channel entirely — a public feed the team subscribed to but didn't systematically cross-reference against their own tree on a schedule shorter than the audit cycle. So the correcting evidence existed in the world for weeks before it reached anyone empowered to act on it, and it reached them by chance timing rather than by design.
The concept this names
This is confirmation bias, and it is worth being precise about where the term applies, because the phrase gets used loosely. Peter Wason's original 1960 experiment asked subjects to discover a rule governing number triples, starting from the example 2-4-6. Subjects who hypothesised "increasing by two" tested sequences like 8-10-12, which confirmed the guess, rather than sequences designed to break it, like 6-4-2 or 1-2-3. The rule was actually just "any ascending sequence," and testing a descending or non-arithmetic triple would have revealed that immediately. Subjects weren't stupid. They reasoned soundly from the evidence they collected. The defect was in what evidence they went looking for.
That is the exact shape of the dependency audit failure. The staff engineer's reasoning, given the query he ran, was sound: no known CVEs in the packages checked, therefore no action needed. The flaw sat one step earlier, at the choice of which packages to check and how far down the graph to go. Raymond Nickerson's 1998 review is useful here because it separates two things that get conflated: motivated bias, where someone wants a particular conclusion to be true, and a simpler positive-test strategy that shows up even when nobody has a stake in the outcome. The staff engineer had no motive to hide a vulnerability. He had a habit of testing the case that was easy to test and had always come back clean. That habit is enough on its own.
Why "more audits" isn't the fix
The obvious response — audit more often — treats this as a frequency problem. It is not. Running the same query five times a month instead of once a quarter finds nothing new if the query never reaches the fourth level of the tree. What was missing was a channel that continuously watched the full graph and flagged any change against advisory feeds, not a periodic human decision about where to look. Once that kind of intake exists — dependency graph resolved fresh on every build, checked automatically against every advisory feed as it publishes, with no human choosing the sampling window — the nineteen-week gap becomes structurally impossible, not merely less likely.
That reframes the incident. A software engineering team already has, in principle, four live streams available: the commit stream, CI results, the incident feed, and dependency advisories. The failure wasn't the absence of a stream. It was that human audit practice sampled those streams selectively and periodically, re-asking the comfortable question instead of the exhaustive one. This is where the concept connects to a larger claim about what kind of system can and cannot fall into this trap by design.
Confirmation bias as an intake failure, and the ladder it exposes
The frozen corpus behind a Large Language Model is the limiting case of this pathology, not an unrelated one. Such a model has not merely stopped seeking disconfirming evidence — it has stopped seeking anything at all past its cutoff. Whatever the corpus contained becomes the entire universe of admissible fact, permanently. No advisory published tomorrow can revise a belief formed today, for the structural reason that nothing published tomorrow can arrive. Applied to the dependency case: a model trained on a corpus current to last year cannot know about this March's advisory, and no amount of clever prompting recovers what was simply never let in.
A Large World Model does better. A bounded, live scene can contradict what was assumed a moment ago — closer to how the dependency graph, freshly resolved, can contradict last month's clean audit. But the correction only reaches as far as the sensor points and lasts as long as the scene does. If nobody scopes the scene to include the fourth level of the transitive tree, the model behaves exactly like the audit that missed it: locally live, globally blind.
| Position | Sampling window | Behaviour under a new advisory |
|---|---|---|
| Large Language Model | closed at training cutoff | cannot register the advisory at all |
| Large World Model | live but bounded to the scene in view | registers it only if the scene includes that stream |
| Large Universe Model | all streams, continuously, revisably | registers it the moment it publishes, and can trace which prior belief it overturns |
The Large Universe Model is the position where this specific defect has no structural foothold, because there is no stopping point built into the architecture and no scene boundary to sit outside of. Every advisory feed, every CI result, every commit is a live stream held as a revisable belief tagged with its own provenance — so that when the March advisory contradicts November's clean audit, the system doesn't need a human to remember which audit that was or to think of re-running it. The contradiction locates its own target and demotes it.
What the objections get right
Two objections deserve a straight answer here, because a reader who has watched "more monitoring" projects fail will already be raising them.
Widening the intake just gives the biased weighting function more material to be selective with. Give a team every feed in the world and they'll still only look at the ones that confirm what they already believe about their own system.
This is correct, and it is the reason the fix above specifies automatic cross-referencing rather than simply subscribing to more advisory feeds. The team in the story already had a dependency advisory feed. Subscription was not the missing ingredient; forced, provenance-tagged confrontation between that feed and the actual resolved graph was. Breadth of intake is necessary but does nothing on its own. What converts it into a remedy is a mechanism that cannot be quietly skipped — a belief about "this tree is clean" that carries the audit date it was last verified against, and that gets automatically flagged stale the moment a new advisory or a new dependency resolution disagrees with it. Without that forcing function, more feeds is just more noise available for the same selective habits.
Some closure is deliberate and good. A security audit needs a fixed scope and a fixed cadence, or nothing is ever auditable — you can't review a moving target.
Fair, and worth conceding fully. An audit scoped to a stated window, checked against a stated set of advisories, is a legitimate engineering artefact — closure applied on purpose, for one bounded question, at a stated time. That is different from a checking process whose sampling habits never get re-examined and whose scope quietly narrows to whatever came back clean before. The remedy is not to abolish scoped audits; it is to keep the underlying evidence base moving continuously underneath them, so that each scoped audit inherits the most current picture of the tree rather than reusing last quarter's comfortable one, and so that the record shows exactly what was known, and when, if a later advisory proves it wrong.