When a CVE lands against a library you depend on, the question your team actually has to answer in the next few hours is not “are we listed as affected” but “by which route could this vulnerable code reach us, and would our scanner even see it?” The evidence suggests a workable rule: scan immediately when the vulnerable code could reach you outside a manifest, through a fork, a vendored copy, or a history of copied code, or when public exploit code appears; for ordinary manifest dependencies, run dependency-tree triage first and spend expensive reachability and clone-detection effort only on flagged candidates. The reason for splitting the response this way is that the two routes have almost opposite failure modes: manifest tooling over-fires on transitive dependencies, and it entirely misses copies that no manifest records.
This article builds that rule from nine studies, one of them a recent self-reported preprint, and flags where the evidence runs out.
One CVE, how many blast radii
The scale of the incoming problem justifies having a standing procedure rather than improvising each time. An average of 212 CVEs are published per day, with reported annual growth of 21.1%, according to the GitHub Popularity Metric paper’s citation of RogoLabs 2025 data. That figure is secondhand, and the same paper notes that only a fraction of published CVEs is ever exploited, so raw volume alone is a poor trigger.
Timing matters more than volume. In 2023 and 2024, the median lag between CVE publication and the first related exploit published on GitHub was six days, per the GPM study’s yearly analysis; by 2025 the median had fallen to one day. That sets the clock for triage: if you are going to react before public exploit code exists, you may have a single day, and your decision procedure has to be cheaper than the incident it prevents.
Meanwhile, the theoretical blast radius of a single upstream flaw can be enormous. A prototype-pollution vulnerability in lodash, a library with over 80 million downloads per month as a dependency, was identified as exposing 4.35 million GitHub projects to potential attack, according to the npm dependency-tree propagation study. Potential is the operative word. That figure counts dependency-tree exposure, not execution; the npm study itself leaves the gap unmeasured, deferring vulnerable-function call-path analysis to future work. The nearest measurement comes from Maven, where only 1.2% of 1.1 million transitively affected projects actually call vulnerable code in their dependencies, a different ecosystem rather than a lodash estimate. That gap between exposure and execution is the counter-evidence that shapes the whole framework below.
Route 1: forks and vendored copies, what manifest scanners never see
The central new evidence is a preprint on CVE-based vulnerability propagation across systems (arXiv:2611.14164), which describes SQVDT, a pipeline that extracts vulnerable-code signatures from CVE-linked patch files and searches for their recurrence in unpatched or reused code across GitHub projects. Critically for triage, it classifies propagation as intra-project (spread within one system, typically across versions) versus inter-project (spread across different systems). The authors report finding hundreds of previously undetected vulnerabilities in well-known software; that count is self-reported, the preprint does not state its dataset scope (ecosystems, time window, languages), and it does not report the actual intra- versus inter-project rates, so treat the framing as a hypothesis about routes rather than a measured distribution.
The mechanism is plausible on independent evidence. Studies cited in the clone-detection literature find 7% to 23% of software systems contain duplicated code fragments. Forks, vendored dependencies checked into your tree, and copied functions are all instances of the same phenomenon: vulnerable code traveling with no manifest entry to record the trip. No dependency scanner, advisory feed, or lockfile diff covers this route. If the vulnerable code is in your repository as a copy, your package manifest will never mention it.
The preprint’s operational recommendations point the same direction: repository handlers should automatically update previous versions when a vulnerability is found in one, and inter-project findings require “collaboration and information sharing with other teams or external organizations.” Read operationally, that is an argument for maintaining a standing inventory of forks, vendored copies, and sibling services that share code with the affected project, so a new CVE becomes a lookup instead of an archaeology project.
Route 2: transitive dependencies, over-caught and under-caught
For code that does travel through manifests, the empirical picture is more precise, and it cuts against scanning everything. The Maven transitivity study reports two findings that should anchor your triage. First, about a third of packages in its dataset are identified as vulnerable if and only if all transitive dependencies are considered, so shallow scans under-report. Second, less than 1% of packages have a reachable call path to vulnerable code in their dependencies, far below what naive dependency-based analysis reports. Dependency-level alerting over-fires by roughly two orders of magnitude relative to call-graph reachability.
Two caveats keep that 1% figure from being a license to ignore transitive alerts. Reachability analysis in that study ignores control flow, so even “reachable” code may be untriggerable if the required input never arrives, meaning the true exploitable fraction is lower still but unknowable from call graphs alone. And the authors note that pruning dependency trees by depth trades recall for computation time, a real constraint if you run fine-grained analysis against a large portfolio.
Ecosystem context changes the numbers. The npm study, built on over 50 million resolved dependency trees, concedes the same limitation from the other side: “the vulnerabilities in dependencies may never actually affect root packages since these vulnerable functions may never be reached.” And the Cargo ecosystem study found that 18% of libraries affected by a vulnerability remain affected in the library’s latest version, on a knowledge graph of 570,563 nodes and 75,922 known vulnerabilities, so “just upgrade to latest” is not a reliable fix in that ecosystem. The Cargo authors explicitly warn that dependency-governance findings do not transfer directly across ecosystems with different technical structures. Treat every rate above as a snapshot of one ecosystem in one window, not a constant.
Route 3: copied code, your weakest instrument
If a fork or vendored copy is flagged, the tool you reach for is clone detection, and the evidence says to distrust it. The IoT vulnerable-clone study documents concrete misses: CVE-2015-8604 and CVE-2020-7996 were detected only by CCFinderSW, a token-sequence-granularity tool, and were invisible to function-granularity detectors because one lacked a function symbol and the other was only a few lines inside one function. If the vulnerable fragment occurs exactly once in a project, there is no clone pair to detect at all. Lowering the similarity threshold catches more but trades missed clones for false positives.
The reliability ceiling is lower than benchmark scores suggest. A generalizability study of CodeBERT found that its 96.5% F1 on BigCloneBench drops significantly on unseen code snippets and functionality IDs, and that Type-4 semantic clones (different syntax, same behavior) can only be safely confirmed by manual validation. The propagation preprint’s own survey of prior tools lands similarly: DECKARD is reported at a 90% false-positive rate, and VulPecker, which found almost 40 vulnerabilities unregistered in NVD, is too slow for massive scanning, all per the preprint’s self-reported account.
The practical consequence: a clean clone scan is weak evidence of absence. Budget manual review for high-consequence copies even when automated detection comes back empty.
Why waiting on the advisory also fails
The other passive strategy, wait for tooling and advisories to tell you, has documented failure modes. The npm fix-lag study reports response times of four to eleven months, only 21.28% of clients reacting to a fix with a client patch landing, and 25.64% (1,389 of 5,417 clients) removing the vulnerable dependency instead of patching. It also identifies a structural blind spot: npm audit does not work when the immediate dependency has not adopted the package-side fixing release, forcing manual review while “client developers have to wait for the propagation of the fixing release.” GitHub’s dependency-alert bot “will not be able to catch everything,” per the same source.
So both passive poles fail: scan-everything drowns you in unreachable findings, and wait-for-the-advisory leaves multi-month windows open exactly when exploit code appears within days.
The triage checklist
Synthesizing the above into a decision procedure:
| Signal at CVE announcement | Evidence | Action |
|---|---|---|
| Vulnerable code could reach you via fork, vendored copy, or known copy history | Manifest tools structurally blind; clone propagation demonstrated (preprint) | Immediate clone-based scan plus manual review of flagged copies |
| Public exploit code or PoC appears, or publication is within days | Median exploit lag fell from 6 days (2023–2024) to 1 day (2025) (GPM study) | Escalate regardless of route; treat reachability analysis as confirmation, not gate |
| Ordinary direct or transitive manifest dependency, no exploit signal | Under 1% reachable in Maven (transitivity study) | Dependency-tree triage first; reachability analysis on flagged candidates only |
| Affected library in an ecosystem with stale latest versions | 18% of affected Cargo libraries vulnerable at latest (Cargo study) | Verify the fix actually landed in the version you would adopt; consider removal |
| Intermediate dependency has not adopted the upstream fix | npm audit failure mode (fix-lag study) | Manual review; do not assume audit fix covers it |
Two implementation notes. First, the checklist is only as good as the inventory behind it: the fork and vendored-copy map is what converts “could this reach us outside a manifest” from a research question into a lookup. Building it is recurring maintenance, but it replaces per-advisory firefighting. Second, clone-detection results need human confirmation at the top of the funnel: given DECKARD’s reported 90% false-positive rate and CodeBERT’s collapse on unseen code, automated clone hits are leads, not verdicts.
I would trial this rule on a past incident before trusting it: take a CVE your team handled in the last year, reconstruct which route the vulnerable code actually traveled, and check whether the rule would have allocated effort correctly. The rule is synthesized from ecosystem snapshots, not validated as a procedure, and your portfolio’s fork density may shift the balance.
What this evidence cannot settle
The limits here are not decorative. The intra- versus inter-project propagation comparison, the framing this article translates into routes, rests on one unreplicated, self-reported preprint that does not state its sampling scope or report its intra- versus inter-project rates; its central claim that cross-system CVE propagation is previously unstudied is likewise self-reported. None of the nine studies measures GitHub fork networks specifically, so fork inheritance is extrapolated from generic code-reuse and clone findings. Reachability figures ignore control flow, so “reachable” overstates exploitability by an unknown amount. Ecosystem findings come from Maven, npm, Cargo, and IoT datasets at different times, and the Cargo authors themselves caution against cross-ecosystem generalization. And the 212-CVEs-per-day figure is a secondhand citation, not an independent audit.
What survives those limits is narrower but still useful: propagation routes differ in tooling coverage, manifest routes are loud and mostly benign, copy routes are silent and occasionally fatal, and the exploit clock, compressed from six days to one, punishes teams that have to build their map during the incident. Maintain the inventory when nothing is on fire, so the next advisory is a lookup with a known budget rather than a guess.
Frequently Asked Questions
How quickly does public exploit code typically appear after a CVE is published?
In 2023 and 2024, the median lag between CVE publication and the first related exploit published on GitHub was six days, per the GPM study’s yearly analysis; by 2025 the median had fallen to one day.
What percentage of transitively affected Maven projects actually call vulnerable code?
The nearest measurement comes from Maven, where only 1.2% of 1.1 million transitively affected projects actually call vulnerable code in their dependencies, a different ecosystem rather than a lodash estimate.
Does upgrading to the latest version always fix a vulnerability in the Cargo ecosystem?
the Cargo ecosystem study found that 18% of libraries affected by a vulnerability remain affected in the library’s latest version, on a knowledge graph of 570,563 nodes and 75,922 known vulnerabilities, so “just upgrade to latest” is not a reliable fix in that ecosystem.

Join the discussion
Share a useful perspective or ask a question about this article.