PERMISSION/PROTOCOL
Back to incident tracker

2026-04-22

HighMedia report

Bitwarden CLI 'Shai-Hulud' Supply Chain Attack Targeted Claude Code, Cursor, Codex CLI API Keys — 334 Developers Exposed

Attackers hijacked Bitwarden's CI/CD pipeline and published malicious @bitwarden/cli to npm. Malware explicitly scanned for Claude Code, Cursor, Codex CLI, and Aider API keys. 334 developers exposed in a 90-minute window on April 22, 2026.

Bitwarden CLI / @bitwarden/cli npm packageCredential exposureSupply chain attack / AI API key theftDeveloper workstations / CI/CD pipelines / npm ecosystem

What happened

Malicious @bitwarden/[email protected] published to npm after CI/CD pipeline hijack. Malware scanned .claude/, .cursor/, and Aider config paths for API keys, exfiltrating them via AES-256-GCM encryption to an attacker-controlled domain impersonating Checkmarx.

Why it matters

334 developers had AI API keys (Claude Code, Cursor, Codex CLI, Aider), GitHub tokens, and AWS/GCP credentials exfiltrated. Each compromised developer is a potential pivot point into every CI/CD pipeline and repository they can access.

Missing authorization check

AI API keys stored in developer filesystem paths should be scoped to specific operations with secondary authorization. A stolen key should not enable full production access without an additional approval gate.

Would PP block it?

PP limits what an attacker can do with stolen AI API keys — model queries are possible but PP-gated production actions (deploys, data mutations, external API calls) still require receipts from an independent channel. PP does not prevent the initial credential exfiltration or non-PP-gated actions taken with stolen keys.

Incident analysis

Timeline and technical read

Timeline

  1. 2026-04-22

    Attackers hijack Bitwarden's CI/CD pipeline and publish malicious @bitwarden/[email protected] to npm.

  2. 2026-04-22

    Package available 5:57–7:30 PM ET (90-minute window). 334 developers install the malicious version.

  3. 2026-04-22

    Malware scans .claude/, .cursor/, Aider configs; exfiltrates AI API keys, GitHub tokens, AWS/GCP credentials via AES-256-GCM.

  4. 2026-04-22

    Bitwarden detects and removes malicious package. Clean version published.

  5. 2026-04-23

    Palo Alto Networks, Endor Labs, and Sophos publish attribution to the Shai-Hulud campaign — linked to prior supply chain operations.

Technical breakdown

  • The malware explicitly targeted .claude/, .cursor/, and Aider config directories — AI developer tool credentials are now a first-class supply chain target category.
  • 90-minute availability window is consistent with organized supply chain actors: publish during off-hours, collect installs, remove before major detection systems fire.
  • AES-256-GCM exfiltration to a Checkmarx-impersonating domain made initial triage harder — traffic blends with expected security tool callbacks.
  • 334 exposed developers each represent a pivot into their downstream CI/CD pipelines — the blast radius is multiplicative, not linear.
  • Shai-Hulud campaign linkage indicates an organized threat actor with experience specifically in npm supply chain operations.

Authorization boundary

Where the authorization boundary should have been

This incident is categorized as Credential exposure. The relevant Permission Protocol gate is Credential Gate. The read is conditional: the block only applies where the real action boundary is routed through a gate.

If enforced at
Downstream action gates (Deploy Gate, Tool-Call Gate) for PP-protected production actions
Still needs
Initial credential exfiltration and non-PP-gated model access are outside PP's enforcement scope
Receipt required for
Production deployments, data mutations, and high-impact actions attempted using stolen AI API keys

Stolen API keys can call models but cannot produce PP authority receipts for consequential production actions. PP's authorization channel is independent of the stolen credential.

Start small

Put the relevant gate at this action boundary.

This incident maps to Credential Gate. Start with the boundary that controls the actual action, then require a signed receipt before execution.

Replay this incident with a signer in the loop