Dependency & Supply Chain Security
debt(d3/e5/b5/t5)
Closest to 'default linter catches the common case' (d3). The term's detection_hints.tools list includes dependabot, snyk, composer-audit, npm-audit, and socket-dev — these are widely available and often enabled by default in modern development workflows. Running `composer audit` or `npm audit` is straightforward and catches known CVEs in dependencies. However, novel supply chain attacks (compromised but not-yet-reported packages) require more specialized monitoring, pushing slightly beyond d3 but not to d5.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix suggests running audit commands, committing lock files, and adding SRI hashes — individually simple tasks. However, remediating dependency security holistically requires updating CI pipelines, reviewing and updating multiple package references, potentially replacing compromised or abandoned packages, and establishing ongoing monitoring processes. For legacy projects with many unlocked dependencies or missing lock files, the effort spans configuration files, deployment scripts, and potentially application code if packages must be swapped.
Closest to 'persistent productivity tax' (b5). Dependency security applies across all contexts (web, cli, queue-worker) per applies_to. Once established, it creates ongoing obligations: reviewing Dependabot PRs, running audits in CI, maintaining SBOMs for regulated projects, and vetting new dependencies before installation. This isn't architectural-level burden (b7-b9) since it doesn't reshape application design, but it's more than localized — every developer adding dependencies must follow security practices, creating a sustained productivity overhead.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field explicitly states developers believe 'pinning dependency versions fully prevents supply chain attacks' when in fact pinned versions can still be compromised if the registry itself is attacked. This is a well-documented gotcha (especially post-event-stream and ua-parser-js incidents) that experienced developers eventually learn, but it contradicts the intuitive mental model that 'locked = safe.' The Log4Shell example in why_it_matters shows how transitive dependencies create hidden exposure even when direct dependencies seem controlled.
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"
}