6.0 KiB
Supply-Chain Incident Response
This playbook is the ECC operator runbook for npm, GitHub Actions, and cross-ecosystem package-registry incidents. It is intentionally conservative: registry signatures, provenance, and trusted publishing are useful signals, but they do not prove that the workflow executed the intended code path.
Current External Trigger
As of 2026-05-15, the active incident class is the May 2026 TanStack npm supply-chain compromise and broader Mini Shai-Hulud campaign. ECC keeps the same IOC sweep for the related npm/PyPI waves because these incidents target package install/publish paths, AI developer-tool configs, and developer credentials:
- TanStack reported 84 malicious versions across 42
@tanstack/*packages, published on 2026-05-11 between 19:20 and 19:26 UTC. - GitHub advisory
GHSA-g7cv-rxg3-hmpx/CVE-2026-45321describes install-time malware that harvests cloud credentials, GitHub tokens, npm credentials, Vault tokens, Kubernetes tokens, and SSH private keys. - Follow-on reporting from StepSecurity, Socket, Aikido, and Wiz describes the same campaign expanding into packages associated with Mistral AI, UiPath, OpenSearch, Guardrails AI, Squawk, and other npm/PyPI packages.
- The live IOC set includes persistence through Claude Code
.claude/settings.json, VS Code.vscode/tasks.json, and OS-levelgh-token-monitorLaunchAgent/systemd services. Remove those persistence hooks before rotating a stolen GitHub token. - The attack chain combined
pull_request_target, GitHub Actions cache poisoning across a fork/base trust boundary, and OIDC token extraction from a GitHub Actions runner. - npm trusted publishing/provenance can confirm a package came from a bound CI identity. It cannot by itself prove that the CI cache, lifecycle scripts, or publish path were safe.
Primary references:
- https://tanstack.com/blog/npm-supply-chain-compromise-postmortem
- https://github.com/advisories/GHSA-g7cv-rxg3-hmpx
- https://tanstack.com/blog/incident-followup
- https://docs.npmjs.com/trusted-publishers/
- https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem
ECC Exposure Check
Run this before a release candidate, after a broad dependency bump, and after any package-registry incident.
npm run security:ioc-scan
node scripts/ci/scan-supply-chain-iocs.js --home
npm ci --ignore-scripts
npm audit signatures
npm audit --audit-level=high
node scripts/ci/validate-workflow-security.js
node tests/scripts/npm-publish-surface.test.js
node tests/run-all.js
If a search hit appears only in documentation examples, note it in the release evidence but do not rotate credentials for a docs-only reference.
Immediate Response
If ECC or a maintainer machine installed a known-bad package version:
- Stop the host from publishing or deploying.
- Preserve evidence before cleanup:
- package manager command history;
package-lock.json,pnpm-lock.yaml, oryarn.lock;- CI run URLs and runner logs;
- npm package versions and tarball integrity hashes;
- outbound network logs where available.
- Treat the install host as compromised if lifecycle scripts may have run.
- Remove persistence hooks before token revocation:
~/.claude/settings.jsonSessionStarthooks and adjacentrouter_runtime.js/setup.mjspayload files;.vscode/tasks.jsonfolder-open tasks and adjacent payload files;~/Library/LaunchAgents/com.user.gh-token-monitor.plist;~/.config/systemd/user/gh-token-monitor.service;~/.local/bin/gh-token-monitor.sh.
- Rotate every credential reachable by the process:
- npm automation tokens and maintainer tokens;
- GitHub PATs, fine-grained tokens, deploy keys, and Actions secrets;
- cloud credentials, Vault tokens, Kubernetes service-account tokens, SSH
keys, and local
.npmrctokens; - any MCP, plugin, or harness credentials available in environment variables or user-scope config.
- Purge GitHub Actions caches for affected repositories.
- Reinstall from a clean environment with
npm ci --ignore-scriptsfirst. - Re-enable lifecycle scripts only after the dependency tree and package versions are pinned to known-clean releases.
GitHub Actions Rules
ECC enforces these rules through scripts/ci/validate-workflow-security.js:
- privileged workflows must not checkout untrusted PR refs;
- workflows with write permissions must use
npm ci --ignore-scripts; - workflows with
id-token: writemust not restore or save shared dependency caches; - workflows that run
npm auditmust also runnpm audit signatures; pull_request_targetworkflows must not restore or save shared dependency caches.
Treat any violation as a release blocker.
Publication Rules
Before tagging or publishing ECC:
- Verify there is no unexpected dependency on packages in the active advisory.
- Use a clean checkout or throwaway worktree for release commands.
- Do not mix PR/test caches with publish jobs.
- Keep
id-token: writelimited to release workflows that do not use shared dependency caches. - Prefer trusted publishing/provenance where supported, while still requiring local package-surface tests and registry-signature verification.
- Confirm npm dist-tag, GitHub release, Claude plugin, Codex plugin, and OpenCode package state in the publication-readiness evidence document.
When To Escalate
Escalate to a maintainer security review before any release or merge if:
- a dependency lockfile references a package named in an active advisory;
node scripts/ci/scan-supply-chain-iocs.js --homefinds Claude Code, VS Code, or OS-level persistence indicators;- a workflow combines
pull_request_targetwith dependency installation, cache restore/save, PR-head checkout, or write permissions; - a release workflow combines
id-token: writewith shared cache usage; - a publish workflow uses a long-lived npm token without a documented reason;
- AgentShield, GitGuardian, Dependabot, npm audit, or registry-signature checks disagree.