
TL;DR: The TeamPCP / Shai-Hulud campaign has turned trusted npm namespaces into short-lived credential-stealing weapons, and npm audit will not save you because it only fires after an advisory exists. Vibe coders need five preventive layers โ lockfile hygiene, isolated installs, pinned actions, runtime egress monitoring, and automatic secret rotation โ wired in before the next typosquat lands.
If you ship with Cursor, Bolt, v0, Claude Code, or Replit and you ran npm install between roughly 5:57 PM and 7:30 PM ET on April 22, 2026, you may have handed over your GitHub tokens, .ssh keys, .env files, shell history, and cloud secrets to TeamPCP. That is the new floor for supply-chain risk in 2026, and it requires a real defense plan.
TeamPCP โ the cluster The Hacker News links to the Shai-Hulud worm family โ is not a one-shot CVE. The Trivy compromise (CVE-2026-33634) entered an active extortion phase weeks before the April 22 npm event, with malicious Docker Hub images pushing the same TeamPCP infostealer that Socket researchers identified in the original Trivy intrusion. The @bitwarden/cli@2026.4.0 incident on April 22 was a separate publish: malicious for roughly 93 minutes (5:57โ7:30 PM ET) before Bitwarden pulled it and shipped 2026.4.1 as a clean re-release of 2026.3.0, per Bitwarden's coordinated disclosure cited by The Hacker News.
The playbook is consistent: take over (or typosquat) a trusted package, publish a release with a credential-stealing postinstall, harvest from ~/.aws, ~/.ssh, .env, gh auth token, browser cookie stores, and shell history, then unpublish before advisory tooling catches up. GitGuardian's 2026 State of Secrets Sprawl report (March 17) documented 29 million new hardcoded secrets on public GitHub in 2025 and an 81% surge in AI-service credential leaks โ so the loot is fat and the attackers know exactly what to grep for.
npm audit, Dependabot, and GitHub Advanced Security are reactive. They fire after an advisory is published, which can be hours or days after the package was already on disk. You need preventive layers.
Your package-lock.json or pnpm-lock.yaml is the only artifact that records exactly which integrity hash you trusted (see the npm docs on package-lock.json). Run lockfile-lint in CI to enforce that every resolved URL points at the registry you actually trust and that integrity is sha512, not sha1. Use pnpm or npm overrides to pin transitive dependencies that have a history of takeover, and reject any PR that mutates the lockfile without a corresponding package.json change. If you use Yarn, turn on strict SSL and checksumBehavior: throw.
The bitwarden-cli postinstall worked because the developer who ran it had GITHUB_TOKEN, AWS keys, and SSH keys sitting on the same filesystem. Move installs into a sandbox: Docker with --network=none for the install step, a devcontainer, or a --ignore-scripts install followed by a manual review of the handful of packages that genuinely need build steps. For one-off CLI tools, use npx --ignore-scripts or pipe through Sigstore-verified containers. Your laptop is not a build server; stop pretending it is.
The Trivy campaign pivoted into CI by exploiting trusted GitHub Actions on a high-profile org account ("aquasecurity"). Pin every uses: line to a full commit SHA, not a tag โ tags are mutable, SHAs are not. StepSecurity's harden-runner action will both audit your workflows and enforce runtime controls. Layer it on with egress-policy: block and an explicit allowlist; if a compromised action tries to POST your GITHUB_TOKEN to an attacker domain, the runner kills the connection and surfaces the attempt in the workflow log. GitHub's own docs.github.com/code-security hub covers the complementary platform-side controls (required reviews, secret scanning, push protection).
Static scanning misses dynamic exfiltration. Run Falco or Cilium Tetragon on your build agents and dev containers with rules that alert on outbound connections from node, python, or npm processes to anything outside your registry and CDN allowlist. On a laptop, Little Snitch or LuLu serves the same purpose โ when a postinstall script tries to reach webhook.site or a fresh Cloudflare worker domain, you want to see the prompt before the request completes. Behavioral analysis tools that flag suspicious network calls in npm packages should be wired into your editor's terminal, not consulted only after a scare.
Assume any secret that has touched a developer machine in the last 90 days is potentially burned. Move every credential into Doppler or 1Password Secrets Automation with short-lived tokens, then build a one-command rotation: gitleaks to detect what leaked, GitHub's fine-grained PAT API to mint a replacement, and a webhook into your secrets manager to fan out the new value. With 29M secrets hitting public GitHub in 2025 alone, the question is not whether you'll need to rotate โ it's whether you can do it in minutes instead of days.
No, but it is a lagging indicator, not a control. Keep it in CI as a backstop, but do not treat a clean npm audit as evidence that an install is safe. Pair it with lockfile-lint for resolved-URL enforcement and runtime egress monitoring (Falco, Tetragon, harden-runner) to catch what static analysis misses.
Check your shell history for npm install or pnpm add calls touching @bitwarden/cli between 5:57 PM and 7:30 PM ET on 2026-04-22. If yes, rotate every GitHub PAT, AWS key, SSH key, and .env value on that machine immediately, audit gh auth status and recent git push events, upgrade to @bitwarden/cli@2026.4.1, and run gitleaks detect against your local repos to see what was readable.
Not entirely, but install with --ignore-scripts by default and explicitly allowlist the handful of packages that genuinely need postinstall (native modules like node-sass or better-sqlite3). pnpm's onlyBuiltDependencies config makes this enforceable across a workspace.
npm audit is reactive; preventive layers (lockfile-lint, sandboxed installs, pinned action SHAs, egress monitoring, fast rotation) are what actually stop credential theft.npm install on the same host that holds your production secrets โ sandbox it with Docker --network=none, a devcontainer, or --ignore-scripts.harden-runner with an egress allowlist on every workflow.Discover more content: