Apache Struts had a patch available on March 7, 2017. Equifax didn't apply it. Ten weeks later, attackers used that unpatched flaw — CVE-2017-5638 — to pull 147 million Social Security numbers out of Equifax's systems, a breach that eventually cost the company $1.4 billion in settlements and fines. That's the defining case study for "known vulnerabilities in dependencies": not a zero-day nobody could have predicted, but a publicly disclosed, patchable bug that sat in production because nobody mapped where the vulnerable library actually ran. Log4Shell (CVE-2021-44228) told the same story at greater scale in December 2021, and the xz-utils backdoor (CVE-2024-3094) showed in March 2024 that even "trusted" upstream maintainers can ship the vulnerability directly. This post breaks down what counts as a known vulnerability, why they keep causing breaches years after patches exist, and how to actually find and fix the ones that matter in your dependency tree.
What Counts as a "Known Vulnerability in Dependencies"?
A known vulnerability in a dependency is a security flaw in third-party code that has already been publicly disclosed and assigned a CVE (Common Vulnerabilities and Exposures) identifier, meaning defenders don't have to discover it themselves — they just have to notice it applies to them. The lifecycle runs through a few public systems: MITRE assigns the CVE ID, NIST's National Vulnerability Database (NVD) publishes a CVSS severity score and technical description, and language-specific advisory databases (GitHub Security Advisories, npm audit, PyPI Advisory Database, OSV.dev) republish it in a machine-readable format that scanners consume. As of mid-2026 the NVD holds more than 240,000 published CVE records, and Google's OSV.dev aggregates advisories across npm, PyPI, Maven, RubyGems, Go, crates.io, and half a dozen other ecosystems. The catch: publication doesn't mean detection. NIST's own backlog crisis, which began in February 2024, left tens of thousands of CVEs sitting unanalyzed without a CVSS score or CPE mapping for months, which breaks scanners that depend on that metadata to match a vulnerability to your specific dependency version.
Why Do Known Vulnerabilities in Dependencies Keep Causing Breaches?
They keep causing breaches because organizations know about the flaw and still don't remediate it fast enough, not because the flaw was hidden. Synopsys's 2024 Open Source Security and Risk Analysis (OSSRA) report found that 96% of the 1,067 commercial codebases it audited contained open source components, and 84% contained at least one known open-source vulnerability — with 74% containing at least one classified as high-risk. Separately, Verizon's 2024 Data Breach Investigations Report attributed roughly 15% of breaches to third-party software involvement, up nearly 3x year over year. The Log4Shell timeline is the clearest illustration of the detection-to-exploitation gap: the CVE was disclosed on December 10, 2021, and Check Point Research recorded attackers attempting exploitation within hours, logging over 800,000 attack attempts in the first three days. Patches don't fail because they don't exist — Apache shipped a fix the same day — they fail because most organizations can't tell which of their thousands of services actually load the vulnerable class in the first place.
How Many Vulnerable Dependencies Does a Typical Codebase Actually Carry?
A typical enterprise codebase carries dependency trees where the direct packages you chose are outnumbered by transitive ones you never explicitly picked, often by a ratio of 5-to-1 or higher in ecosystems like npm and Maven. Synopsys OSSRA data puts the average number of open source components per application at 526 in the codebases it scanned, and open source now makes up 77% of the average commercial application's code by volume. Each of those components pulls in its own dependencies: a single create-react-app scaffold in 2024 could resolve to 1,300+ npm packages in node_modules before a developer writes a line of application code. This is why a vulnerability in a package like lodash, axios, or log4j-core doesn't affect one team — it affects every service that transitively depends on it, often four or five layers removed from anyone's package.json or pom.xml, which is exactly why security teams routinely underestimate their real exposure until an SBOM forces the full tree into view.
What's the Difference Between "Vulnerable" and "Exploitable"?
A dependency is vulnerable if it contains the flagged code; it's exploitable only if your application actually calls the vulnerable function in a way an attacker can reach from outside. This distinction is why vulnerability counts and real risk diverge so sharply: a 2023 Endor Labs study of Java applications found that on average, only about 9.5% of vulnerabilities flagged by traditional SCA tools involved code that was actually reachable from the application's own call paths. The rest were dead code, test-only dependencies, or functions never invoked in production. Log4Shell is again instructive here in reverse: it was so dangerous specifically because the vulnerable JndiLookup class was reachable through an extremely common code path — any logged string containing an attacker-controlled ${jndi:...} payload — which is a big part of why it triggered a global incident rather than a routine patch cycle. Reachability analysis is the difference between a backlog of 3,000 CVEs and a prioritized list of the 40 that a security team can actually fix this sprint.
How Do You Actually Detect Known Vulnerabilities Across Your Dependencies?
You detect them by generating a complete, versioned inventory of every direct and transitive dependency — a Software Bill of Materials (SBOM) — and continuously matching it against vulnerability feeds rather than scanning once at release time. The SBOM mandate isn't theoretical: Executive Order 14028 (May 2021) and the subsequent NTIA minimum elements guidance pushed SBOM delivery into federal procurement requirements, and CISA's 2025 guidance extended expectations around SBOM consumption for critical infrastructure vendors. In practice this means producing SBOMs in CycloneDX or SPDX format at build time, ingesting the SBOMs of the third-party vendors and open source projects you depend on, and running that combined inventory against advisory sources like OSV.dev, GHSA, and NVD on a continuous basis — not just when a developer opens a pull request. The xz-utils incident in March 2024 is the cautionary case for why this needs to run upstream, too: the backdoor was inserted into a compression library used by OpenSSH indirectly through liblzma, and it was caught only because Microsoft engineer Andres Freund noticed a 500-millisecond SSH login delay during unrelated performance debugging — not because any scanner flagged it, since the malicious code was deliberately hidden from static analysis and only activated in specific build configurations.
How Safeguard Helps
Safeguard turns a raw CVE list into a fixable one by running reachability analysis across your actual call graphs, so you see which of your flagged dependencies are truly exploitable from your application's entry points versus which are dead weight in a node_modules folder nobody executes. Griffin AI, Safeguard's detection engine, correlates that reachability signal with exploit maturity and your runtime deployment context to rank findings the way an attacker would prioritize them, not the way a CVSS base score alone would. Safeguard generates CycloneDX and SPDX SBOMs automatically at build time and ingests SBOMs from vendors and upstream projects, giving you one continuously updated inventory instead of a stack of point-in-time scan reports. When a known vulnerability is confirmed reachable, Safeguard opens an auto-fix pull request with the minimum safe version bump already tested against your build, cutting the gap between disclosure and remediation from weeks to hours.