Vulnerable and Outdated Components: The Risk You Inherited
A typical application today is mostly other people's code: frameworks, libraries, runtimes, and their transitive dependencies, often hundreds of packages deep. Vulnerable and Outdated Components is the category that reckons with this reality — the risk that somewhere in that inherited mass sits a component with a publicly known vulnerability and a public exploit to match. It ranked sixth in 2021 and is one of the few categories driven by industry survey rather than test data, because it is so hard to measure and so easy to get wrong.
The defining feature of this risk is that the vulnerability is already known. Unlike a novel bug an attacker must discover, a vulnerable component comes with a CVE, a description, and frequently a working proof of concept. The window between disclosure and mass exploitation can be measured in hours. If you are running the affected version, you are exposed to an attack anyone can download and run.
Why it is hard to stay ahead
- You may not know what you run. Transitive dependencies — the libraries your libraries pull in — rarely appear in anyone's mental model, yet they execute with the same privileges as your code.
- Updating is not free. A new version can break compatibility, so teams defer upgrades, and deferred upgrades accumulate into a backlog of known-vulnerable code.
- Disclosure is asymmetric. Defenders must patch everything; an attacker needs one unpatched instance.
- End-of-life software lingers. Components that no longer receive security fixes at all keep running because replacing them is expensive.
The Log4Shell episode of late 2021 made the category concrete for everyone. A critical vulnerability in a ubiquitous logging library meant that organisations first had to answer a question many could not: where is this component even used? The scramble was not to write a fix — one was released quickly — but to locate every place the vulnerable version was running. That is the true difficulty of A06: you cannot patch what you cannot find.
└─ web-framework 3.2
└─ http-parser 1.4
└─ json-lib 0.9 (known CVE, transitive, unseen)
Managing inherited risk
- Maintain a software bill of materials. Generate and keep an SBOM so you can answer "do we use X?" in minutes, not days.
- Scan dependencies continuously with software composition analysis, and gate builds on newly disclosed critical vulnerabilities.
- Patch on a schedule and on alert. Track advisories for everything you depend on, and treat critical disclosures as incidents.
- Remove unused dependencies. Every component you drop is one you never have to patch.
- Prefer maintained, reputable sources and retire end-of-life components before they become unpatchable liabilities.
This category rewards boring diligence over brilliance. The organisations caught flat-footed by the next Log4Shell will not be those who wrote bad code, but those who could not quickly say what their software was made of. Discovery is the whole game: an accurate, current inventory of your components is the only thing that turns a five-alarm scramble into a routine patch.
- Pull one dependency manifest and pick the oldest library in it. Look up whether its version has known CVEs — one unpatched component is often the whole story.
- Check the front end: view source and note the versions of any JS libraries loaded. Public version strings tell an attacker exactly which exploits to try.
The full, at-scale version — building the real SBOM and matching every direct and transitive component against active advisories, continuously — is what our assessment (and SecStudio agents) runs for you.