OWASP A06:2021 Vulnerable and Outdated Components: Detection and Prevention
TL;DR
OWASP A06:2021 Vulnerable and Outdated Components covers the risk that comes from running third-party software with known vulnerabilities — direct dependencies, transitive dependencies, runtime libraries, and unsupported component versions. It is the OWASP category that SAST does not catch; the dedicated tooling discipline that solves it is Software Composition Analysis (SCA), paired with a Software Bill of Materials. The category was largely ignored in earlier Top 10 editions until Log4Shell (CVE-2021-44228) made the cost of being unable to answer "do we use this component" impossible to ignore. Detection requires walking the full transitive dependency tree on every build and continuously monitoring shipped releases against vulnerability advisory databases.
A06:2021 Vulnerable and Outdated Components used to be called "Using Components with Known Vulnerabilities" and sat at A09 in the 2017 edition of the OWASP Top 10. For most of the decade between its introduction and 2021, it was the category teams quietly ignored — there was no headline incident driving prioritization, the fix felt like janitorial work, and the existing tooling for finding vulnerable components was clunky and noisy. Then, on December 9, 2021, the Apache Log4j team published an advisory for CVE-2021-44228. Within hours, security teams worldwide were running incident response and discovering that they had no idea where Log4j was actually deployed in their estates because most of them had inherited it transitively, three or four dependency levels deep, through frameworks they had not chosen consciously.
That experience repositioned A06 in the 2021 edition: it moved up to sixth place and was renamed to highlight outdated and unsupported components, not just components with known CVEs. It is the OWASP category most directly addressed by a single tooling discipline. SAST finds defects in code you wrote. DAST probes the running application from the outside. Neither is positioned to walk a dependency tree, match every component-version pair against vulnerability databases, and surface CVEs in libraries you did not write. That is what Software Composition Analysis (SCA) exists to do. This guide walks through what A06 covers, why it moved up, the real incidents that defined it, the CWE mappings scanners report against, and the layered detection and prevention strategy that actually works.
What A06 Covers
A06:2021 is broader than "we have a CVE in a library." It is the OWASP umbrella for any failure to safely manage the third-party software your application depends on, and it spans several distinct sub-problems that scanners and audit checklists treat differently.
Components with known vulnerabilities. The headline case. A library, framework, runtime, or OS package in your application is on a version with a publicly disclosed CVE, and a fixed version is available. The classic example is shipping Log4j 2.14.1 in late 2021 after CVE-2021-44228 was published, or shipping Apache Struts 2.3.5-2.3.31 in 2017 after CVE-2017-5638 was patched. The vulnerability is real, exploitable, and often weaponized within days of disclosure.
Outdated and unsupported components. A library whose maintainers have stopped shipping security fixes — either because the project is end-of-life, because the version branch is no longer supported, or because the maintainer has gone silent. There may be no CVE filed against your version yet, but you are running code that nobody is patching, and a future advisory will leave you with no upgrade path that does not require a major rewrite.
No inventory of components in use. The structural failure under almost every Log4Shell horror story. The application uses a component, but nobody on the team can answer the question "do we use this component, and if so where" within minutes. The lack of inventory is the meta-vulnerability — it converts every future advisory into a multi-day archaeology project.
Missing patch process. Even when teams know they have a vulnerable component, they often have no defined process for patching it: no SLA tied to severity, no automation for raising upgrade pull requests, no owner assigned to dependency hygiene. The CVE sits open for months because patching is nobody's primary job.
Missing transitive dependency visibility. The defect that defined Log4Shell. Most teams track the libraries they explicitly declare in package.json, pom.xml, or requirements.txt. They do not track the full resolved tree — the libraries those libraries pull in, and the libraries those libraries pull in, often four or five levels deep. A typical Node.js application with 30 declared dependencies resolves to 800-1,500 packages once npm install finishes. The other 770-1,470 are exactly where vulnerabilities tend to hide.
Why It Moved Up to #6 in 2021
The category moved from A09:2017 to A06:2021 for two reinforcing reasons. The first is methodology: OWASP rebalanced the 2021 ranking to weight incidence rate more heavily than exploitability and impact, and vulnerable-component findings appear in nearly every application that any modern SCA tool scans. The second is industry experience between the two editions, which finally made the category impossible to defer.
Between 2017 and 2021, two events reframed how the industry thought about supply chain risk. SolarWinds (December 2020) showed that a build-pipeline compromise at a single vendor could cascade into thousands of downstream customers — including U.S. federal agencies and Fortune 500 enterprises — through an auto-updating component nobody had reason to suspect. Log4Shell (December 2021) showed that a critical RCE in a single ubiquitous Java library could put the entire Java ecosystem into incident response within a single news cycle. Neither incident was a defect in code anyone audited as their own. Both were defects in code that arrived through the supply chain.
The other shift is quantitative. Modern applications are between 70 and 90 percent third-party code. The application code your team wrote and reviews is the visible tip of the iceberg; the open-source libraries, frameworks, runtime engines, and OS packages compiled and deployed alongside it are the bulk of what runs in production. Treating that bulk as out of scope for security review is no longer defensible. For a deeper look at why transitive depth dominates the modern attack surface, see transitive dependencies as attack surface.
Real-World Incidents
Equifax (2017). The breach that exposed roughly 147 million records was traced to a known vulnerability in Apache Struts 2 — CVE-2017-5638, a remote code execution flaw in the framework's Jakarta Multipart parser. A patch had been available for over two months at the time of the breach. Equifax's web application was running an unpatched Struts version, an attacker triggered the RCE, and the rest unfolded over months of undetected lateral movement. The post-incident analysis pointed at the absence of a reliable inventory of which applications used Struts and which versions — exactly the inventory gap A06 names.
Log4Shell (December 2021, CVE-2021-44228). The defining supply-chain event of the past decade. A critical remote code execution in Apache Log4j 2 affected the vast majority of Java applications in production — most of which had never declared Log4j as a direct dependency. The library arrived transitively through Spring Boot, Apache Solr, Elasticsearch, application servers, and dozens of other widely used frameworks. Teams with full dependency-tree visibility identified affected services within hours. Teams without it spent days running file-system searches across production hosts, uncertain whether they had found everything. For a complete walkthrough of how the incident unfolded and the lessons it left behind, see Log4Shell and the supply chain lesson.
Spring4Shell (March 2022, CVE-2022-22965). A remote code execution in Spring Framework's data-binding mechanism, affecting Spring MVC and Spring WebFlux applications running on JDK 9 and above. The advisory dropped while the industry was still settling from Log4Shell, and the response was a near-replay of December 2021: teams that had built dependency-tree visibility into their pipelines could enumerate affected services immediately; teams that had not went back into incident-response mode. The practical lesson was that the tooling investment made under Log4Shell pressure was already paying back within months.
polyfill.io (June 2024). A widely embedded JavaScript polyfill service was acquired by a new operator and began serving malicious payloads to roughly 100,000 sites that had embedded its CDN script. The compromise was not a CVE in the traditional sense — there was no version-pinned dependency to update, because the affected sites were loading the script live from a third-party CDN. The incident drove the industry toward more cautious patterns around third-party script inclusion: subresource integrity, self-hosted polyfills, and strict CSP policies. It also reinforced that supply chain risk extends beyond build-time dependencies into runtime third-party code.
Relevant CWE Mappings
A06:2021 aggregates a small number of CWEs in the official OWASP mapping. The four below are the entries scanner output most commonly reports against, plus the legacy mapping that connects A06:2021 back to its A09:2017 predecessor.
| CWE | Title | Where It Shows Up |
|---|---|---|
| CWE-937 | OWASP Top 10 2013: A9 (Components with Known Vulns) | Legacy mapping for the original A09 category — reported by older scanners |
| CWE-1035 | OWASP Top 10 2017 Category A09 (Using Components with Known Vulns) | 2017 reference category — bridges A09:2017 to A06:2021 in tracking systems |
| CWE-1104 | Use of Unmaintained Third-Party Components | Library whose upstream is no longer publishing security updates |
| CWE-1395 | Dependency on Vulnerable Third-Party Component | Application uses a component-version pair with a known CVE |
CWE-1395 is the entry SCA tools most often map findings to in 2026 — it captures the canonical "you depend on this component-version pair, and it has a CVE" finding shape. CWE-1104 is the unmaintained-component variant, which matters because an unmaintained library often has no future patch path even when no CVE is currently filed. CWE-937 and CWE-1035 are legacy mappings that older scanners still emit; treat them as equivalent to A06 for triage purposes.
Detection: Why SCA Is the Answer
A06 is the OWASP category where the layered-tooling argument has a clean, single answer: Software Composition Analysis. SAST analyzes the source code your team wrote and is not built to walk a dependency tree of binary artifacts pulled from a package registry. DAST probes the running application from the outside and is not built to enumerate component-version pairs. Neither is positioned to do what A06 detection actually requires: parse the lockfile or build manifest, resolve the full transitive tree, and match every node against vulnerability advisory databases.
What an SCA scan actually does. The tool starts with the build manifest for each ecosystem in the repository — package-lock.json for npm, pom.xml for Maven, build.gradle for Gradle, requirements.txt or poetry.lock for Python, packages.lock.json for NuGet, go.sum for Go modules, Cargo.lock for Rust, composer.lock for PHP, Gemfile.lock for Ruby. From the manifest the scanner resolves the full transitive tree, producing a list of every component-version pair that will end up in the deployed artifact. It then matches each pair against curated vulnerability data — typically NVD as the baseline, plus GitHub Advisory Database for ecosystem-specific entries, plus researcher-curated feeds for issues not yet in the public databases. Each match becomes a finding with a severity, a fixed-version recommendation, and a path showing how the vulnerable component arrived in the tree. For the full mechanics, see SCA scanning explained.
Direct vs transitive findings. The distinction matters for remediation. A direct finding — a library you declared explicitly — can usually be patched by bumping the version in your build manifest. A transitive finding requires you to either upgrade the parent that pulled in the vulnerable child, exclude the vulnerable child and pin a fixed version, or wait for the parent to release a patched version that includes the fix. Tools that report only direct dependencies miss most of the actual attack surface. Tools that report transitive depth without a clear upgrade path leave teams with findings they cannot act on. Both halves are required.
The scanner landscape. The SCA market includes commercial offerings, open-source baselines, and built-in features in cloud platforms and CI providers. Each makes different trade-offs around vulnerability database coverage, transitive depth, ecosystem support, license compliance, and remediation tooling. For a category-by-category comparison of the major options, see SCA tools buyer's guide.
SBOM as the Foundation
A Software Bill of Materials (SBOM) is the inventory artifact that closes the meta-gap A06 names. The SBOM is a machine-readable list of every component-version pair shipped in a release artifact — the dependency tree frozen at build time, recorded in a standard format (CycloneDX or SPDX), and stored alongside the artifact for the life of the release. With an SBOM in hand, the next time a Log4Shell-class advisory drops, you answer "do we use this component" with a one-line query against your SBOM index, not a multi-day forensic exercise across production hosts.
The SBOM has moved from voluntary best practice toward regulatory expectation. U.S. Executive Order 14028 (May 2021) directed federal procurement to require SBOMs from software vendors, and the EU Cyber Resilience Act extends similar expectations to manufacturers placing products on the European market. The practical implication for any vendor selling into regulated buyers is that SBOM generation needs to be a build-pipeline output, not a custom artifact assembled under deadline pressure during an incident. For the discipline in depth, see SBOM practitioner guide.
The SBOM is also the input to the broader supply chain integrity story: build attestations, signed releases, and frameworks like SLSA that move beyond "what is in this build" toward "can we prove this build came from this source." For background on how SBOM fits into supply chain integrity, see what is SLSA.
Prevention
Run SCA in CI on every pull request. Vulnerable dependencies introduced in a feature branch should be flagged before they merge, with severity-aware policy gates: a critical-severity new finding fails the build, a medium-severity new finding adds a comment without blocking. The cost of catching a vulnerable component at PR time is minutes; the cost of catching it in production is incident response.
Continuously monitor shipped releases. Build-time scanning is necessary but not sufficient. A vulnerability disclosed today may affect a release you shipped three months ago. Continuous monitoring re-evaluates each shipped artifact against the current state of the vulnerability database, so the moment a new CVE is published against a component you ship, you receive an alert with the affected service and version path.
Generate and store an SBOM with every release. Build pipelines should emit a CycloneDX or SPDX document for every artifact and store it alongside the artifact registry. The SBOM is the answer to every future incident-response question of the form "are we affected by this CVE."
Define a patch SLA tied to severity. Critical CVEs in production dependencies need a defined patch window — typical industry practice is 24 to 72 hours for critical, 7 to 30 days for high. Without a written SLA tied to a named owner, patching slips indefinitely.
Automate dependency upgrades. Tools like Dependabot, Renovate, and integrated upgrade-PR features in mature SCA platforms reduce the cost of staying current. The economics are clear: routine version bumps applied weekly are cheap; emergency patches applied under incident pressure are expensive.
Require SBOMs from vendors. Procurement contracts should require third-party software vendors to ship SBOMs with every release. The asymmetry is otherwise impossible to close: you cannot patch a vulnerable component you cannot see, and you cannot see what your vendor will not tell you.
Where GraphNode SCA Fits
GraphNode SCA is the dedicated dependency-security tool in the GraphNode platform. It walks the full transitive dependency tree across the major package managers — npm, Maven, Gradle, pip, NuGet, Go modules, Cargo, Composer, and RubyGems — and matches every resolved component-version pair against a curated vulnerability dataset combining NVD, the GitHub Advisory Database, and security researcher feeds. Findings include severity, fixed-version recommendations, and the dependency path showing how the vulnerable component arrived in the tree, so direct and transitive issues are both actionable.
Beyond vulnerability matching, the tool covers the adjacent disciplines A06 hygiene depends on. License compliance identifies license conflicts and risks across the dependency tree, with policy enforcement so a non-compliant license in a new dependency fails the build. SBOM generation emits a standard-format inventory artifact for every build, ready to ship alongside release artifacts and answer future incident-response queries. Automated remediation opens upgrade pull requests with the recommended fixed version and the affected paths summarized inline, so a developer can review and merge the patch in minutes rather than reconstructing the dependency context from scratch.
For A06 specifically, GraphNode SCA is positioned as the primary detection layer. SAST and DAST do not replace it for this category — the data flow patterns SAST traces and the runtime behavior DAST probes are not where vulnerable-component findings live. The honest mapping is that A06 belongs to SCA, and a complete OWASP-aligned program runs SCA continuously on every build and every shipped release. For the broader picture of how the OWASP categories map to AppSec tooling, see the OWASP Top 10 hub.
Frequently Asked Questions
What is OWASP A06:2021?
OWASP A06:2021 Vulnerable and Outdated Components is the OWASP Top 10 category that covers the risk of running third-party software with known vulnerabilities — direct dependencies, transitive dependencies, runtime libraries, and unsupported component versions. It was previously titled "Using Components with Known Vulnerabilities" at A09 in the 2017 edition and was renamed and moved up to A06 in 2021 to reflect both the rise of supply chain attacks (SolarWinds, Log4Shell) and the broader scope of outdated and unmaintained components, not just components with filed CVEs.
What is the difference between A06 and supply chain attacks?
A06:2021 covers the consumption side: your application uses a third-party component that has a known vulnerability or is no longer maintained. Supply chain attacks are the production side: an attacker compromises an upstream component or its build pipeline so the malicious code propagates to every downstream consumer (SolarWinds, polyfill.io, malicious npm package incidents). The two are related — A06 hygiene reduces your blast radius from supply chain attacks because a maintained inventory and SBOM let you identify affected systems quickly — but they are different threat models. A06 is largely addressed by SCA; supply chain attacks additionally require build integrity controls, signed artifacts, and frameworks like SLSA.
Can SAST detect vulnerable components?
No. SAST is built to analyze source code your team wrote and to trace data flow patterns through that code. It is not positioned to walk a dependency tree of binary artifacts pulled from a package registry, resolve transitive dependencies, or match component-version pairs against vulnerability advisory databases. That work is what Software Composition Analysis (SCA) exists to do. SAST and SCA are complementary disciplines, not substitutes — most OWASP categories are SAST or DAST territory, but A06 is the one category that belongs squarely to SCA.
Do I need both SCA and an SBOM tool?
In most cases the SBOM is a feature of a mature SCA platform rather than a separately-procured tool — the same scanner that resolves the dependency tree to find vulnerabilities can emit the resolved tree as a CycloneDX or SPDX SBOM. The right framing is functional rather than tooling: you need vulnerability matching (the SCA scan) and you need a stored, machine-readable inventory (the SBOM). Whether those come from one product or two depends on the platform, but having both is non-negotiable for credible A06 hygiene and increasingly for regulatory compliance under EO 14028 and the EU Cyber Resilience Act.
How fast should I patch a critical CVE in a dependency?
Industry practice for critical-severity CVEs in production dependencies is a patch window of 24 to 72 hours from advisory publication, with high-severity issues on a 7 to 30 day window. The exact numbers should be encoded as a written SLA tied to a named owner — without that, patching reliably slips. Two factors compress the window further: whether the vulnerability is being actively exploited in the wild (Log4Shell mass scanning was visible within hours of disclosure, and CISA added it to the Known Exploited Vulnerabilities catalog within days) and whether the affected service is internet-facing. The practical patch cadence is enabled by the prior investments: continuous monitoring detects the issue immediately, automated upgrade PRs reduce the time to a tested fix, and SBOM lookup answers "where is this deployed" in minutes instead of days.