← Back to all labs
OWASP A03 · LAB ENVIRONMENT

Software Supply Chain Failures

Software Supply Chain Failures occur when attackers compromise the dependencies, build tools, or update mechanisms your application relies on. Try the interactive playground below to see how a malicious package can exfiltrate secrets during install — and how pinning and script-blocking stop it.

OWASP Top 10 · 2025 · A03 — Software Supply Chain Failures

The Silent Package: How One Dependency Can Compromise Everything

Modern applications are built on hundreds of third-party packages, build tools, and CI/CD pipelines — and every one of them is a trust decision. Software supply chain failures happen when unpinned or unverified dependencies, typosquatted package names, compromised maintainer accounts, or malicious build scripts (like postinstall hooks) get pulled into your codebase and executed with full developer privileges. Run the simulation below to see how a single npm install can turn into a credential-stealing attack — and how lockfiles, pinning, and script restrictions stop it cold.

Pinned & Verified Dependencies
OFF — Vulnerable Install
STATUS: IDLE PACKAGE: left-pad-utils@2.3.7
// terminal output will appear here — click RUN to begin
⚠ Malicious postinstall script executed
The package’s postinstall hook ran automatically and silently during install — with the same permissions as your build process — and exfiltrated environment secrets to an external host.
✓ Supply chain policy enforced
npm ci resolved the exact version pinned in the committed lockfile and verified its integrity hash. Lifecycle scripts were blocked by policy, so the postinstall payload never ran. No secrets left the machine.
✗ Vulnerable — package.json & install
{
  "name": "checkout-service",
  "dependencies": {
    "left-pad-utils": "^2.0.0"  // loose range, auto-upgrades
  }
}

# no package-lock.json committed
$ npm install            # resolves "latest matching", no hash check
# postinstall scripts run automatically, unrestricted
  • Loose semver range (^2.0.0) lets any minor/patch — including a compromised one — install silently
  • No lockfile enforced → every environment can resolve a different, unverified version
  • Lifecycle scripts (postinstall) execute with full local/CI privileges by default
  • No integrity or provenance verification of what actually got downloaded
✓ Secure — package.json & install
{
  "name": "checkout-service",
  "dependencies": {
    "left-pad-utils": "2.3.7"  // exact pinned version
  }
}

# package-lock.json committed to repo
$ npm ci --ignore-scripts   # lockfile-exact + hash-verified install
# SBOM generated, provenance/signature checked (Sigstore/SLSA)
Why this matters: This mirrors a real and recurring attack pattern seen across the npm, PyPI, and RubyGems ecosystems — attackers compromise a maintainer account or publish a typosquatted package, then rely on the fact that install-time scripts run automatically and unreviewed. A single unpinned dependency deep in your tree can quietly hand over CI secrets, cloud credentials, or signing keys before anyone notices.

How to Detect & Fix