Back to Cheat Sheets

📦 Keep Your Components Secure

OWASP Top 10 Proactive Controls (2024) - C6

CORE CONTROL

📋 What Is This Control?

Keep Your Components Secure is the proactive control of managing the security of every first- and third-party component your software depends on, across its entire lifecycle - from the moment you choose it, through every release you ship, to the day you retire it. A modern application is mostly code you did not write: frameworks, libraries, runtimes, base images, and the long tail of transitive dependencies. The governing principle is you cannot secure what you cannot see: everything starts with a complete, accurate inventory.

C6 Proactive Control
Supply Chain Focus Area
OWASP 2024 Proactive Controls

🎯 What It Prevents

  • RCE via known-vulnerable library: a transitive dependency ships a published remote-code-execution flaw
  • Exploitation of public CVEs: scanners weaponize disclosures within hours of publication
  • Malicious / compromised packages: hijacked or hostile releases run attacker code at install time
  • Dependency confusion: a public look-alike outranks your internal package
  • Typosquatting: near-miss package names install malicious code
  • Compromised build pipelines: tainted-but-signed artifacts from a trusted vendor
  • Vulnerable base-image / OS packages and abandoned EOL components with no fix
  • Transitive blindness & integrity drift: unpinned, unhashed, invisible dependency trees

🧭 How It Works

1. Inventory: generate an SBOM (CycloneDX/SPDX)
covering direct AND transitive components
↓
2. Source & pin: trusted registries, scoped
internal packages, committed lockfiles + hashes
↓
3. Scan: SCA gate in CI fails critical findings
↓
4. Monitor: Dependabot/Renovate open update PRs;
deployed releases re-scanned continuously
↓
5. Patch on a cadence + emergency lane; retire unused & EOL

❌ Without This Control

// package.json - floating ranges, no lockfile committed { "name": "billing-service", "dependencies": { "express": "^4", // any 4.x - resolves differently over time "lodash": "*", // literally any version "left-pad": "latest" // whatever is newest at install time } } // .gitignore package-lock.json ← lockfile ignored (!) - builds not reproducible // .npmrc - internal packages can resolve to the PUBLIC registry registry=https://registry.npmjs.org/ // internal package published unscoped as "billing-utils" // an attacker publishing public "billing-utils@99.0.0" wins by version! // CI - no scanning, no integrity check $ npm install ← may pull newer, unreviewed transitive code $ npm run build $ deploy ← known-vulnerable code ships unnoticed

✅ Applying the Control

// package.json - human-readable, but the lockfile decides { "dependencies": { "express": "4.19.2", "lodash": "4.17.21" } } // package-lock.json is COMMITTED and records integrity hashes: // "lodash": { "version": "4.17.21", "integrity": "sha512-v2kDEe..." } // .npmrc - scope internal packages to an internal registry ONLY @myorg:registry=https://npm.internal.myorg.com/ registry=https://registry.npmjs.org/ // internal package is "@myorg/billing-utils" - the scope can never // resolve to the public registry, defeating dependency confusion // CI - reproducible, hash-verified install + SCA gate + SBOM $ npm ci # fails if lock & manifest disagree $ npm audit --audit-level=high # native auditor gate $ trivy fs --severity HIGH,CRITICAL --exit-code 1 . # SCA gate $ npx @cyclonedx/cyclonedx-npm --output-file sbom.json # SBOM # Python equivalent: pin WITH hashes, reject anything that mismatches $ pip install --require-hashes -r requirements.txt $ pip-audit --strict

✓ Implementation Checklist

  • SBOM (CycloneDX/SPDX) generated per build, covering transitive components
  • SCA gate in CI fails builds on high/critical findings
  • Deployed releases re-scanned continuously against new advisories
  • Lockfiles committed and enforced (npm ci, hashed requirements, pinned Maven)
  • Public registries proxied through a controlled internal repository
  • Internal packages scoped so they cannot resolve to the public registry
  • Dependabot/Renovate opening scheduled update PRs
  • Regular patch cadence plus a documented emergency path
  • Unused dependencies removed; EOL components tracked and replaced
  • Container base images minimal, scanned, and rebuilt regularly
  • Build pipeline hardened; artifacts signed with SLSA provenance
  • Virtual patches tracked as temporary, with a real-fix deadline

🔍 Tools & Techniques

SCA & Scanning:

OWASP Dependency-Check npm audit pip-audit Snyk Trivy Grype

Inventory & Automation:

Syft (SBOM) CycloneDX Dependabot Renovate Sigstore / cosign SLSA

How to Verify:

  • Confirm an SBOM is produced and stored for every build
  • Break the build with a known-vulnerable version - CI must fail
  • Query "which releases ship component X?" - answerable in seconds
  • Check lockfiles are committed and CI uses npm ci / --require-hashes
  • Verify internal package scopes cannot resolve publicly
  • Scan container images and confirm bases are rebuilt on a schedule

🌍 Why It Matters

These are recurring classes of incident this control is built to prevent - described as patterns, with no invented CVEs or figures.

  • Critical flaw in a ubiquitous library (Log4Shell-class): a widely used logging library disclosed a critical RCE. Because it was buried deep in transitive trees, most organizations could not even answer "are we affected?" for days. Teams with a current SBOM and SCA answered in minutes and patched first.
  • Dependency confusion: an attacker publishes a public package matching an internal name with a higher version; misconfigured tooling pulls the attacker's code into the build. Scoped packages and source pinning close it.
  • Typosquatting & malicious packages: near-miss names or hijacked maintainer accounts run attacker code at install time.
  • Compromised build pipeline: adversaries ship a tainted-but-signed artifact to all of a vendor's customers - the reason provenance (SLSA) and pipeline hardening matter for what you publish too.

📌 Quick Tips

  • DO NOT track only your manifest - most risk is transitive
  • DO NOT float versions or skip integrity hashes
  • DO NOT treat a WAF virtual patch as the permanent fix
  • DO generate an SBOM and scan continuously, not just at release
  • DO source from trusted registries and pin with lockfiles
  • DO patch on a cadence with a fast emergency lane
  • DO remove unused dependencies and replace EOL components early