Back

C6: Keep Your Components Secure - How to Implement

The Implementation Model

Implementing this control means turning the ten core practices into automated, repeatable steps that run without heroics. The organising idea is a pipeline: see everything, verify what enters, watch continuously, and update on a rhythm. Nothing below relies on a human remembering to check—each step is wired into tooling that fails loudly when something is wrong.

First principle: you cannot secure what you cannot see. Every other step assumes you have a complete, current inventory. Start there.

Step 1: Build an Inventory / SBOM

Generate a Software Bill of Materials that lists every component—direct and transitive—with name, version, license, and origin. Produce it automatically as a build artifact so it is always current, and store it where incident responders can query it.

# Generate a CycloneDX SBOM
# Node
npx @cyclonedx/cyclonedx-npm --output-file sbom.json

# Python
cyclonedx-py environment --output-format json --outfile sbom.json

# From a container image or filesystem (language-agnostic)
syft dir:. -o cyclonedx-json=sbom.json
syft myapp:1.4.2 -o spdx-json=sbom.spdx.json

Step 2: Run SCA in CI and Continuously

Software Composition Analysis matches your components against vulnerability databases. Run it two ways: as a gate in CI that fails a build introducing a critical issue, and continuously against already-deployed artifacts, because new advisories land daily against code you already shipped.

# Native package-manager auditors
npm audit --audit-level=high
pip-audit --strict

# OWASP Dependency-Check (multi-ecosystem, CI-friendly)
dependency-check --project myapp --scan . --failOnCVSS 7

# Snyk (SaaS SCA)
snyk test --severity-threshold=high

# Trivy / Grype scan the SBOM or the image directly
trivy fs --severity HIGH,CRITICAL .
grype sbom:sbom.json --fail-on high

Step 3: Pin Versions with Integrity Hashes

Commit lockfiles so every build resolves to the exact same bytes, and so a tampered artifact is rejected by its integrity hash. Floating ranges (^, ~, latest) are fine in the manifest for humans, but the lockfile is what actually installs—and it must be committed and enforced.

Step 4: Source from Trusted Origins

Only install components from official, trusted registries, and verify their integrity. This is where you defeat dependency confusion, typosquatting, and malicious packages.

Step 5: Monitor and Automate Updates

Subscribe your codebase to advisory feeds and let automation open the update pull requests. This closes the disclosure-to-patch gap that attackers race you on.

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule: { interval: "weekly" }
    open-pull-requests-limit: 10
  - package-ecosystem: "pip"
    directory: "/"
    schedule: { interval: "weekly" }
  - package-ecosystem: "maven"
    directory: "/"
    schedule: { interval: "weekly" }

Step 6: Patch on a Cadence

Updating is a routine, not a fire drill. Define a regular cadence for normal updates and a fast lane for emergencies, and put automated tests behind both so upgrades are safe to merge.

Step 7: Minimize and Retire

Every dependency you do not need is attack surface you did not have to carry. Actively shrink the tree.

Step 8: Secure the Pipeline and Provenance

Your build system is one of the most privileged places in your estate and a prime supply-chain target. Harden it and prove what it produced.

Step 9: Scan Containers and Base Images

Treat the OS layer as dependencies too. A clean application on a stale base image is still vulnerable.

# Fail a build on vulnerable OS or app packages in the image
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:1.4.2
grype myapp:1.4.2 --fail-on high

Step 10: Virtual Patching as a Stopgap

Sometimes you cannot upgrade immediately—a fix is not yet released, or the upgrade is a major, risky change. A virtual patch (a WAF rule or runtime filter that blocks the known exploit pattern) can reduce exposure while you prepare the real fix.

A Maturity Path

LevelWhat is in place
1 - ReactiveLockfiles committed; someone runs npm audit occasionally.
2 - GatedSCA runs in CI and fails builds on critical findings; Dependabot/Renovate open update PRs.
3 - VisibleSBOM generated per build; deployed releases re-scanned continuously; trusted-source proxy enforced.
4 - HardenedScoped internal packages, container scanning, EOL tracking, and a defined patch cadence with an emergency lane.
5 - AssuredSigned artifacts with SLSA provenance, verified signatures on ingest, and drift/exception governance across the fleet.

Implementation Checklist

Next Steps