Mystery DigitalTalk to us
Hardening the Dependency Supply Chain: What SBOMs Don't Catch
SecuritySupply Chain

Hardening the Dependency Supply Chain: What SBOMs Don't Catch

Mystery Digital · 2026-01-08 · 4 min read

Software bill of materials generation has become a checkbox item — most enterprise procurement processes now require one, most CI pipelines now produce one, via syft, cdxgen, or a language-native tool. That's genuine progress. It's also given a lot of engineering teams a false sense of coverage, because an SBOM is a snapshot of declared dependencies, and the attacks that matter most in 2026 exploit the gap between what's declared and what actually gets executed at build or install time.

The threat model has moved past "known CVE in an old version"

Dependency scanning for known vulnerabilities (via Dependabot, Snyk, or npm audit) catches the attack pattern from five years ago: a maintainer's package has a disclosed CVE, you're on the affected version, you upgrade. That's necessary and now largely automated. The attacks causing real damage now are different in kind — compromised maintainer accounts publishing malicious versions of legitimate, widely trusted packages (the event-stream and ua-parser-js incidents are the canonical examples, and 2025 saw several npm and PyPI incidents follow the identical pattern), typosquatted packages that survive because a build script has a single-character typo, and postinstall scripts that exfiltrate environment variables or CI credentials the moment npm install runs — before your application code executes at all, and before any static scanner gets a chance to look at it.

Lockfiles are necessary and not sufficient

A committed lockfile pins exact versions, which stops the most naive version of the attack: a semver-range dependency silently pulling in a malicious patch release. It doesn't stop a compromised maintainer from publishing a malicious version at the pinned version if you haven't locked yet, and it doesn't stop the lockfile itself from being updated to a malicious version by a routine npm update that nobody scrutinizes at the diff level because lockfile diffs are enormous and unreadable by design.

The control that actually closes this gap is provenance verification, not just version pinning. npm supports Sigstore-based provenance attestation for packages published from CI with npm publish --provenance, letting you verify a package was built from the source repository it claims, not uploaded by hand from a compromised maintainer laptop. We require provenance verification in CI for any dependency update PR touching packages with postinstall scripts, which we treat as a separate, higher-scrutiny risk category — the majority of real-world npm supply-chain compromises we've reviewed used a postinstall script as the execution vector.

Postinstall scripts deserve a default-deny posture

Most teams don't realize how many of their transitive dependencies run arbitrary code on install. Run npm ls --all --parseable | xargs -I{} sh -c 'test -f {}/package.json && node -e "..."'-style auditing (or simpler, pnpm's built-in --ignore-scripts combined with an explicit allowlist) and the number is usually higher than expected — often dozens of packages in a mid-sized application. Our default for new enterprise builds is --ignore-scripts at install time with a curated allowlist for the handful of legitimate build tools (native binary installers like esbuild or sharp) that genuinely need it. Everything else that wants to run code at install time gets reviewed before it's added to the allowlist, not after an incident.

CI runners are part of your supply chain, not infrastructure you can ignore

The build environment that produces your production artifacts has credentials to your registry, your cloud provider, and often your signing keys. A compromised dependency that exfiltrates CI environment variables doesn't need to touch production code at all — it just needs to run once during a build. Scope CI credentials to the minimum required for the specific job (short-lived, workload-identity-federated cloud credentials rather than long-lived static keys), and run dependency installation in an isolated step with no network egress beyond the package registry, so even a compromised postinstall script has nowhere to send what it finds.

SBOMs are the record, not the control

Keep generating them — they're the artifact that lets you answer "were we affected by CVE-X" in minutes instead of days during the next disclosure, and enterprise customers will keep asking for them. Just don't mistake the record for the defense. The defense is provenance verification, default-deny on install-time code execution, and tightly scoped CI credentials — controls that stop a compromise from happening, rather than documentation that helps you find it after it already has.

← Back to blog