Dependency & Supply Chain Security
Also Known As
TL;DR
Explanation
Modern applications depend on hundreds of third-party packages. Each dependency is a potential attack surface — either through a known vulnerability (CVE) or through supply chain compromise (an attacker modifying a legitimate package). Transitive dependencies (dependencies of dependencies) are the highest-risk category: you never explicitly chose them, you may not know they exist, and they can contain critical vulnerabilities. Key controls: lock files (composer.lock, package-lock.json) pin exact versions including transitives; automated scanning (Dependabot, Snyk, composer audit, npm audit) alerts on newly disclosed CVEs; SRI hashes verify CDN-loaded scripts haven't been tampered with; minimal dependency hygiene (fewer packages = smaller attack surface). Supply chain attacks have surged since 2018: event-stream (2018), SolarWinds (2020), Log4Shell (2021), and XZ Utils (2024) all demonstrate that widely-trusted dependencies are high-value targets.
Common Misconception
Why It Matters
Common Mistakes
- Not committing lock files (composer.lock, package-lock.json) — running install without a lock file installs unpinned latest versions, allowing unexpected breaking changes and undetected compromise.
- Running composer update or npm update in CI without reviewing what changed — any update could introduce a compromised version.
- Loading CDN scripts without SRI integrity hashes — if the CDN is compromised, malicious code runs on every user's browser.
- Ignoring automated CVE alerts (Dependabot PRs, npm audit warnings) — known vulnerabilities remain exploitable until patched.
- Installing packages with broad permissions (postinstall scripts) without reviewing them — malicious packages often use lifecycle hooks to execute code at install time.
Avoid When
- Do not use wildcard (*) or very broad version ranges (^major, ~major.minor) in production dependency specifications.
- Do not auto-merge dependency updates without reviewing the changelog and running tests — automated updates can introduce breaking changes or compromised versions.
When To Use
- Apply dependency security controls to every project with third-party dependencies — no exceptions.
- Use npm ci instead of npm install in CI pipelines to enforce exact lock file versions.
- Generate and commit a Software Bill of Materials (SBOM) for regulated or enterprise projects.
Code Examples
<!-- CDN script with no integrity check -->
<script src="https://cdn.example.com/library.js"></script>
# composer.json without committed composer.lock
# Running: composer install (installs latest, ignores lock)
// package.json with broad version ranges
"dependencies": {
"lodash": "*"
}
<!-- CDN script with SRI hash -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"
integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs"
crossorigin="anonymous"></script>
# Commit and use the lock file
# composer install (uses composer.lock)
# npm ci (uses package-lock.json, stricter than npm install)
// Pin exact versions in package.json for production deps
"dependencies": {
"lodash": "4.17.21"
}