Security
Supply-chain incident runbook
How Matter responds to npm supply-chain compromises — the audit, rotation, and pinning playbook. Internal engineering reference; published for enterprise transparency.
Last updated
When an npm package in Matter's dependency tree is compromised, the response follows this playbook. The May 2026 TanStack incident (GHSA-g7cv-rxg3-hmpx) is the worked example; the runbook generalises.
Reflexes (first 30 minutes)
-
Identify the advisory. Pull the affected package list from GitHub:
gh api /advisories/<GHSA-ID> \ --jq '.vulnerabilities[] | "\(.package.name)\t\(.vulnerable_version_range)\t\(.first_patched_version)"' -
Grep
bun.lock. Every affected package, every version. The lockfile encodes resolved versions in the form"<pkg>": ["<pkg>@<version>", ...:for pkg in <affected names>; do grep -n "\"$pkg\": \[\"$pkg@" bun.lock || echo "OK: $pkg not resolved" doneIf zero matches, the resolved dependency tree is clean. Move to step 3. If any match, jump to Rotation.
-
Lockfile-touch forensic. Find every commit that modified the lockfile near the incident window:
git log --all --pretty=format:'%h %ai %an %s' -- bun.lock gh run list --created='<DATE>' --json databaseId,createdAt,workflowNameFor each install that ran during the incident window, capture the host (laptop hostname or CI runner ID) and the time delta from advisory publication.
Rotation (if any resolved version matches)
Treat every host that ran bun install during the window as compromised
per the npm-malware threat model. The malware runs at postinstall time,
so even a transient install — one where the resolver later backed away
from the malicious version — is enough to exfiltrate.
Local dev hosts:
- GitHub PAT and SSH keys (
~/.ssh/) - npm token (
~/.npmrc) - AWS credentials (
~/.aws/credentials) and config (~/.aws/config) - GCP credentials (
~/.config/gcloud/) - Anthropic, Clerk, Stripe, Neon, PostHog, Sentry, Resend, Knock, Basehub,
Svix, Arcjet keys in
.env.localfiles
CI / production:
- Every GitHub Actions secret (
gh secret list, thengh secret setfor each) - Every Vercel environment variable (
vercel env ls, thenvercel env rm+vercel env add) - Every key validated by a
keys.tsfile inpackages/*— those are the load-bearing secrets for the running platform.
Pinning (always, regardless of match)
Defense-in-depth: pin the unaffected versions explicitly so a future
republication cannot silently upgrade past them. Add to root
package.json
under overrides:
"overrides": {
"<package>": "<exact-known-good-version>"
}Bun honors overrides for both direct and transitive resolutions. The
SHA-512 hashes in bun.lock are the real integrity guarantee — overrides
just keep them stable across reinstalls.
Continuous monitoring
Two layers run continuously in this repo:
- Dependabot — weekly version-update PRs, plus immediate security-update PRs on GHSA disclosure. Driven by the GitHub advisory feed; surfaces known CVEs.
- Socket — behavioral scan on every PR that touches
bun.lockor anypackage.json. Scores packages on network access, postinstall scripts, obfuscated code, and known-suspect publisher patterns. Surfaces zero-day attacks before GHSA assigns an ID.
Both layers are necessary. Dependabot caught the May 2026 TanStack compromise after the GHSA was filed (hours after publish). Socket flagged it within minutes of publish, before any advisory existed.
Why this matters for Matter customers
Matter handles US legal-entity formation. The platform's blast radius is larger than the typical SaaS — a compromised entity formation can ship incorporator authority to the wrong address. Supply-chain hygiene is a first-class compliance concern, not an engineering nice-to-have. This runbook is published (not only kept internal) so enterprise procurement reviewers can see the posture without an NDA.
Worked example — GHSA-g7cv-rxg3-hmpx (2026-05-11)
Full audit record: audit/tanstack-postmortem-2026-05-11.md.
- 84 malicious versions across 42
@tanstack/*packages published 19:20–19:26 UTC. - Matter's resolved lockfile contained zero affected packages — only the
table,query,store, andvirtualfamilies, which were untouched. - The single
bun installof the day ran 27 minutes after the window closed, during a brief period when npm was still serving malicious versions, but the resolver did not select any. - No CI installs ran on May 11. Vercel had no relevant deployments.
- Verdict: not exposed. No rotation indicated. Defense-in-depth pins
added across the seven resolved
@tanstack/*packages.