← Back to OWASP Top 10 for Web Applications
A06:20214 min read read

Vulnerable and Outdated Components

Track dependencies, scan for known CVEs, and keep libraries and frameworks patched.

URL: trusteed.io/academy/web-security/vulnerable-and-outdated-components

Vulnerable and Outdated Components covers the risk of using libraries, frameworks, and other software dependencies with known security vulnerabilities — whether because a dependency was never updated after a fix shipped, because the project doesn't track what dependencies it actually has (directly and transitively), or because a component reached end-of-life and stopped receiving security patches entirely. This is fundamentally a supply chain risk category: the vulnerability isn't in code your team wrote, but your application inherits it fully once it's included.

What Is This Category?

Modern applications are assembled from dozens to hundreds of open-source dependencies, most pulled in transitively (a direct dependency's own dependencies, several layers deep) without a developer ever directly choosing or reviewing them. A vulnerability disclosed in any one of these — at any depth — becomes an exposure the moment it's disclosed, if the application hasn't updated past the vulnerable version. The category also covers using components without knowing their versions or provenance at all, using components no longer maintained (no available patches even if a vulnerability were found), and failing to monitor for newly disclosed vulnerabilities in components already in use, which requires ongoing vigilance rather than a one-time check at initial adoption.

Why AI Coding Assistants Get This Wrong

AI assistants generate code that imports and uses libraries based on training data that reflects whatever versions were common at the time of training, or whatever the developer's existing package.json/requirements.txt specifies — neither of which reflects real-time vulnerability status. An assistant has no live connection to vulnerability databases unless explicitly given that context or tooling, so it will confidently write code using a library version that happens to have a critical, actively exploited CVE disclosed after its training cutoff, with no way to know that on its own.

Vulnerable Pattern

// package.json — dependencies pinned or left unconstrained with no update discipline
{
  "dependencies": {
    "lodash": "4.17.11",
    "axios": "*",
    "express": "^4.16.0"
  }
}
No lockfile committed. No automated dependency vulnerability scanning in CI.
No process for tracking newly disclosed CVEs against components already in production.

Secure Pattern

// package.json — explicit, current versions; lockfile committed for reproducibility
{
  "dependencies": {
    "lodash": "^4.17.21",
    "axios": "^1.7.4",
    "express": "^4.19.2"
  }
}
# CI pipeline — automated dependency scanning on every build, not just at initial setup
- name: Dependency vulnerability scan
  run: npm audit --audit-level=high
- name: SBOM generation
  run: cyclonedx-npm --output-file sbom.json

The meaningful difference isn't the version pinning syntax — it's the presence of continuous, automated scanning that catches a newly disclosed vulnerability in an already-deployed dependency, rather than relying on someone remembering to manually check.

Copy-Paste Rules for Cursor, Claude Code, and Codex

---
description: Vulnerable and outdated components — dependency hygiene and continuous scanning
alwaysApply: true
---

# Dependency Security Rules

- When adding a new dependency, use a current, actively maintained version
  — never pin to an old version without a specific, documented reason.
- Always commit a lockfile (package-lock.json, yarn.lock, poetry.lock, or
  equivalent) to ensure reproducible builds and enable reliable
  vulnerability scanning against exact resolved versions.
- Include automated dependency vulnerability scanning (e.g., `npm audit`,
  `pip-audit`, Dependabot, Snyk, or equivalent) in the CI pipeline for any
  new project — do not treat this as optional tooling to add later.
- Prefer actively maintained libraries with a recent release history over
  abandoned or infrequently updated alternatives, especially for
  security-relevant functionality (authentication, cryptography, parsing).
- When generating a Dockerfile or container definition, pin the base image
  to a specific, current, non-deprecated tag — never `latest` for anything
  intended for production — and include a step to scan the resulting image.
- Do not silence or ignore dependency vulnerability warnings without an
  explicit, documented justification (e.g., the vulnerable code path is
  genuinely unreachable) — flag them for review rather than suppressing them.
- Generate or update a Software Bill of Materials (SBOM) as part of the
  build process for projects where dependency provenance matters for
  compliance or security review.

Verification Checklist

  • All dependencies are pinned to current, actively maintained versions with a committed lockfile
  • Automated dependency vulnerability scanning runs on every build/PR, not just periodically
  • Container base images are pinned to specific, current tags, never latest, and scanned for vulnerabilities
  • No dependency vulnerability warnings are suppressed without documented justification
  • An SBOM is generated and maintained for projects with compliance or supply-chain review requirements
  • A process exists for monitoring newly disclosed CVEs against components already in production, not just at initial adoption
  • Continuous scanning covers dependencies alongside application code — see Trusteed's vulnerability scanner for software composition analysis integrated into ongoing scans

Frequently asked questions

Is "if it isn't broken, don't update it" a reasonable approach to dependency management?

No, specifically for security-relevant updates — a dependency can be functionally stable and simultaneously carry a newly disclosed, actively exploited vulnerability. Functional stability and security currency are different properties, and deferring security patches because "nothing looks broken" leaves a known, disclosed vulnerability unaddressed.

How is this different from Improper Inventory Management (API9)?

[API9:2023](https://trusteed.io/academy/api-security/improper-inventory-management) is about not knowing which API endpoints and versions exist and are reachable. Vulnerable and Outdated Components is about not knowing (or not updating) which software dependencies your application relies on — both are inventory problems, but at different layers: endpoints versus libraries.

Does using a well-known, popular framework guarantee its dependencies are safe?

No. Popularity correlates with more scrutiny and faster patching on average, but popular frameworks still disclose vulnerabilities regularly (Log4Shell being the canonical example of a hugely popular, widely embedded library with a critical flaw) — continuous scanning is necessary regardless of a dependency's popularity.