OWASP Top 10:2021 — A06: Vulnerable and Outdated Components
Welcome back to this OWASP Top 10 deep dive. Today’s topic — Vulnerable and Outdated Components — might not sound exciting at first, but it’s a silent killer. Why?
Because it’s about the dependencies your app relies on, not just the code you write. And chances are, most of your application is open source or third-party.
This one’s especially relevant for modern development, where so much of our code isn’t our code.
Full series:
- A01: Broken Access Control
- A02: Cryptographic Failures
- A03: Injection Attacks
- A04: Insecure Design
- A05: Security Misconfiguration
- A06: Vulnerable and Outdated Components (you are here)
- A07: Identification and Authentication Failures
- A08: Software and Data Integrity Failures
- A09: Security Logging and Monitoring Failures
- A10: Server-Side Request Forgery (SSRF)
What Does This Mean?
Modern apps are built like Lego towers — we don’t write everything from scratch. We use:
- Frameworks (like Spring, Django, Express)
- Libraries (for auth, logging, templating, etc.)
- Containers (base images, runtime environments)
- Even entire services via SDKs (like Stripe, Twilio)
The problem? Those packages age. Some contain vulnerabilities. Others haven’t been maintained in years. And it only takes one unpatched flaw in a dependency to bring the whole stack crashing down.
Real-World Examples
The Python pyyaml Problem
A few years ago, apps using pyyaml with yaml.load()
were vulnerable to arbitrary code execution — if an attacker could get their YAML processed. The safe method was yaml.safe_load()
, but the insecure one was often used by default.
Log4Shell (Log4j Zero-Day)
In 2021, a critical vulnerability in the popular Java logging library Log4j allowed attackers to execute remote code just by sending a specially crafted string to a log message. Many apps were vulnerable even if they didn’t use Log4j directly — because a dependency of a dependency did.
Outdated Docker Base Images
A container image built on an outdated Debian or Alpine base might carry dozens of known CVEs. And many dev teams never update base images after the initial FROM alpine:3.11
.
How Attackers Exploit This
Attackers use tools like Shodan or OSS scanning to identify apps running vulnerable libraries. They don’t need to break your code — they just need you to run code someone else forgot to secure.
Exploits might include:
- Remote code execution (RCE)
- Privilege escalation
- Leaking secrets from memory or logs
- Compromising the supply chain via package registries
How Engineers Can Defend Against This
Here’s the good news: you don’t need to eliminate third-party dependencies. But you do need to manage them like critical infrastructure.
- Maintain an Accurate SBOM
A Software Bill of Materials (SBOM) is a list of all components (and versions) used in your app. Tools like Syft, npm list, or pipdeptree can generate them automatically.
You can’t patch what you don’t know you’re using.
- Use Dependency Scanners
Run tools like:
- npm audit, yarn audit
- pip-audit, safety
- OWASP Dependency-Check
- Snyk, GitHub Dependabot, or GitLab security scanning
These flag known vulnerabilities and often suggest fixes or upgrades.
- Patch Regularly
Establish a habit of dependency hygiene:
- Set up alerts for vulnerable packages.
- Schedule routine updates (weekly or sprint-based).
- Lock versions, but don’t ignore updates.
- Avoid Abandoned Libraries
If a package hasn’t been updated in years and has open CVEs, replace it. Use well-maintained, community-supported options — even if they’re less flashy.
- Harden the Supply Chain
- Use signed packages where possible (e.g. npm’s integrity field).
- Pin hashes (requirements.txt, package-lock.json) to prevent surprise updates.
- Consider tools like Sigstore or SLSA to verify what you’re building from.
Real-World Case: Hidden Vulnerabilities
A fintech startup used a logging library that was 3 versions out of date. That lib pulled in a dependency that had an insecure HTTP client.
One day, a researcher discovered you could exploit the client to send data to arbitrary domains — meaning log messages could be weaponised.
No one in the dev team even knew that dependency existed.
That’s why transitive dependencies matter — not just what you import, but what your imports import.
Final Thoughts
Outdated components are like rust in your infrastructure — quiet, slow, and often invisible until something breaks.
Security isn’t just about writing safe code — it’s about keeping your entire stack secure.
Next up: A07: Identification and Authentication Failures → We’ll look at how broken login, weak passwords, and session mishandling still lead to serious breaches — even in 2025.
Leave a comment