Your lockfile trusts a moving target.
One poisoned release or repointed CI tag can inherit developer credentials and pipeline tokens. Supply Core quarantines fresh packages, verifies integrity, and rejects mutable references before they reach the build.
Scroll / case file ↓Five failures that collapsed the time between publish and compromise.
Not hypothetical. Recurring.
- 01
MAY 2026
Mini Shai-Hulud / TanStack
42 packages, 84 artifacts. @tanstack/react-router at ~12M weekly downloads. PR → cache poisoning → OIDC token pulled from runner memory → publish. First npm attack carrying valid SLSA provenance.
Filed / StepSecurity postmortem
SLSA alone is dead as a defense.
Age quarantine blocks the fresh publish; provenance on a poisoned artifact changes nothing.
- 02
2025–2026
Shai-Hulud v1 / v2 / v3
Self-replicating npm worm spreading through pre/postinstall scripts. Destructive payload triggers on token revocation — a naïve “revoke first” incident response burns the host.
Filed / Public incident writeups
Install-time execution is the blast radius.
Frozen fallback installs a known-good version instead of the fresh, worm-carried release.
- 03
2026
PyTorch Lightning / axios / LiteLLM
Compromised releases were being pulled within 6–42 minutes of publish. Registry-side detection and takedown cannot move faster than CI.
Filed / Public incident writeups
Publish-to-pull windows are measured in minutes.
Publish-age policy treats every too-fresh release as hostile until it clears quarantine.
- 04
NOV 2025
shanhai666 / NuGet
9 packages, ~9.5k downloads, ~99% functional cover, time bombs scheduled for 2027 and 2028. Sharp7Extend typosquats the Siemens S7 PLC library. A slow-burn class that defeats install-time scanning.
Filed / Public disclosure writeup
Malware that waits years looks clean today.
OSV advisory checks and contentHash verification on packages.lock.json catch drift when the record catches up.
- 05
MAR–APR 2026
Trivy + Bitwarden CLI / TeamPCP
Same actor as the TanStack attack. Entry was pull_request_target plus a tag force-push — not a dependency at all. The defense surface is bigger than dependencies.
Filed / StepSecurity postmortem
Mutable CI references are a supply chain too.
scan-actions and scan-pipelines reject anything not pinned to a full 40-character SHA.
A mutable reference enters CI. The build stops.
Mechanism / package quarantine
- 01Fresh release appears on the registry.
- 02Age, integrity, and OSV are checked.
- 03Release outside policy is held.
- 04Known-good satisfying version keeps CI moving.
Specific controls. Explicit scope.
Every row names the file, policy, and command. No “supports everything” claim.
| Target | Input | Checks | Command |
|---|---|---|---|
| 01npm | package.json | age quarantine · integrity · OSV · frozen fallback | snapshot-npm |
| 02PyPI | requirements.txt exact pins | age · sha256 · hash validation · OSV | snapshot-pip |
| 03NuGet | packages.lock.json | age · contentHash verification · OSV | snapshot-nuget |
| 04GitHub Actions | .github/workflows/* | full 40-character SHA pinning | scan-actions |
| 05Azure Pipelines | azure-pipelines*.yml | task and external checkout pinning | scan-pipelines |
| 06Docker | Dockerfile and compose | static sha256 digest pinning | scan-docker |
One local system. Six refusal points. Signal moves left to right, then returns to the machine.
One firewall. Six layers.
policy active- 01
LOCK THE REFERENCES
Reject mutable infrastructure
GitHub Actions must resolve to full 40-character SHAs. Docker images must carry sha256 digests. Azure Pipelines get task and checkout pinning checks.
$ scan-actions · scan-pipelines · scan-docker
EXIT 2 / BLOCK CI↓ - 02
RESOLVE THE PACKAGE
Verify what the lockfile names
npm, exact-pin PyPI, and NuGet snapshots check registry age, package integrity, and OSV advisories before trust is granted.
$ snapshot-npm · snapshot-pip · snapshot-nuget
ALLOW / WARN / HOLD↓ - 03
CONTROL INSTALLATION
Quarantine the fresh release
The local npm proxy holds versions inside policy. When possible, it serves the latest known-good frozen version that still satisfies the requested range.
$ docker compose up --build
QUARANTINE / FALL BACK↓ - 04
INSPECT THE BYTES
Scan before advisories exist
Verified archives pass through built-in malware and AI-agent rules. Optional GuardDog adds install-hook, credential-access, exfiltration, and obfuscation heuristics.
$ scan-package --guarddog
SCORE / BLOCK / REVIEW↓ - 05
WATCH THE MACHINE
Re-evaluate every checkout daily
The macOS radar discovers repositories, inventories supported lockfiles, batches OSV checks with a local cache, and writes a morning report.
$ install_machine_eval.py --home-scope
REPORT / RETRY HOLDS↓ - 06
SHARE THE SIGNAL — OPTIONAL
Publish status, not source code
The self-hosted server accepts authenticated snapshots and exposes read-only status JSON and a live SVG card. Repository paths, ranges, and file contents stay local.
$ serve · /api/v1/status
REMOTE SCAN / STATUS
Your machine is the firewall.
- 01Package policy runs through a local caching proxy.
- 02A daily macOS radar inventories lockfiles and checks OSV.dev with a local 24-hour cache.
- 03No SaaS account, cloud dashboard, agent daemon, or telemetry.
- 04An optional self-hosted service publishes status without source code.
Security software should survive your inspection.
Read the source, review the threat model, and run the checks locally. Trust is earned in code, not a dashboard badge.