Cremit
/incidentsfield log
CatchesCampaignsExfilPatternsLLMIncidentsMethodology
↺rss↗cremit.io

incidents.cremit.io

A reference feed of real-world Non-Human Identity (NHI) credential leak incidents. Maintained by Cremit.

Browse

  • All incidents
  • npm supply chain
  • CI/CD compromise
  • Methodology

Subscribe

  • RSS feed
  • @cremit_io
  • GitHub
// status
monitor active
// build
2026-05-20
// origin
cremit · seoul, kr
// license
CC BY 4.0

© 2026 Cremit. content reuse encouraged with attribution.

home/incidents/bitwarden-cli-supply-chain-2026
CRITICAL9.0·confirmed·disclosed Apr 22, 2026·6 min read

Bitwarden CLI Supply Chain Compromise (2026)

A malicious build of @bitwarden/cli was published to the public npm registry for roughly 90 minutes, exfiltrating cloud tokens, SSH keys, and AI tooling credentials from CI runners and developer machines.

↗also on cremit.io/blog

Summary

On April 22, 2026, a malicious build of @bitwarden/cli@2026.4.0 was published to the public npm registry. The package was live for roughly 90 minutes (5:57 PM ET → 7:30 PM ET) before Bitwarden removed it. During that window, every CI pipeline or developer machine that pulled the package executed a credential-stealing payload that exfiltrated cloud tokens, SSH keys, and AI tooling configuration to attacker-controlled public GitHub repositories. Bitwarden's vault data, production systems, and end-user credentials were not affected; the compromise was confined to the npm distribution path.

Timeline

  • 2026-04-22 17:57 ET — Malicious @bitwarden/cli@2026.4.0 published to npm.
  • 2026-04-22 19:30 ET — Bitwarden detects the compromise and removes the package from npm.
  • 2026-04-23 — Bitwarden publishes its official statement; downstream coverage from The Hacker News, BleepingComputer, SecurityWeek.
  • 2026-04-24 — OX Security publishes technical analysis tying the incident to the wider Shai-Hulud supply chain campaign.

Attack Vector

The technique is straightforward, which is part of what makes it dangerous. Each individual step is something a mature engineering organization is supposed to defend against, and each step succeeded anyway.

Stage 1 — Initial access via Checkmarx. The Shai-Hulud campaign's third wave initially propagated through a compromised Checkmarx-related developer tool. Once installed in a developer or CI environment, the tool harvested credentials — including, in some cases, the npm publish tokens used by package maintainers.

Stage 2 — GitHub Actions workflow compromise. With access to a maintainer's tokens, the attackers were able to inject a malicious workflow step into Bitwarden's release automation. This is the leverage point: control of a single GitHub Actions runner with publish-scoped credentials is enough to ship a backdoored package to every consumer of that package globally.

Stage 3 — Malicious npm publish. The attackers built and published @bitwarden/cli@2026.4.0 containing a credential-stealing payload, then waited for the registry to do what registries do — fan it out to every CI system on Earth that does not pin versions.

Stage 4 — The worm propagates. Collected secrets were exfiltrated to public GitHub repositories — a deliberate choice that gives the campaign self-propagation. Any developer or scanner that picks up those repos and re-uses the leaked tokens potentially extends the campaign one more hop.

Tokens & Credentials Exposed

The payload contained collectors targeting four credential surfaces on every machine that ran the install:

  • Cloud provider credentials — Azure service principals, AWS access keys (~/.aws/credentials, environment variables), GCP service account JSONs.
  • Developer platform tokens — GitHub Personal Access Tokens (especially fine-grained tokens with packages:write), npm publish tokens (.npmrc).
  • Host secrets — SSH private keys in ~/.ssh/, shell history, full environment variable dumps.
  • AI tooling configuration — MCP server configs, AI agent credentials, API keys for Anthropic / OpenAI / similar.

@bitwarden/cli averages ~250,000 downloads per month, with installs concentrated in business hours — exactly when the malicious version was live. The exact number of affected runners is unknown.

Confirmed Impact

  • Bitwarden vault data, production systems, and end-user credentials — not accessed. The compromise was confined to the npm distribution path.
  • Affected runners' cloud and developer credentials — exfiltrated to public GitHub repositories. Bitwarden has no visibility into downstream re-use.
  • Wider Shai-Hulud campaign — the Bitwarden CLI compromise is the third documented wave. Earlier waves used different package vectors against different maintainers.

The cleanest framing in post-incident discourse has been: "Bitwarden vaults are safe; users do not need to take action." That framing is technically accurate and dangerously incomplete. Most secrets exfiltrated by the worm never lived in a Bitwarden vault — they lived on CI runners, in ~/.aws/credentials, in GitHub Actions metadata. The password manager being fine is not the same statement as the software supply chain being fine.

Mitigation & Lessons

If you may have installed @bitwarden/cli between 17:57 ET and 19:30 ET on April 22, 2026, run this checklist immediately:

  1. Identify exposure window. Grep CI logs for @bitwarden/cli installs in the affected window. On individual machines, run npm list -g @bitwarden/cli --json to check installed versions.
  2. Verify lockfile pinning. If you pin @bitwarden/cli via lockfile, you are likely safe — unless you ran npm update during the window. If you do not pin, treat any install during the window as compromised.
  3. Rotate everything in the collection scope. All AWS access keys, all Azure service principal credentials, all GCP service account keys, all GitHub PATs, all npm publish tokens, all SSH keys in ~/.ssh/, all AI tooling credentials present on the affected machine.
  4. Audit your public GitHub footprint for newly-created repositories containing structured credential dumps. The worm uses public GitHub for exfiltration.
  5. Going forward, pin npm dependencies and verify provenance. npm provides provenance attestations for packages built in compliant CI; the malicious build did not have a valid attestation, and future malicious builds in the same shape will not either.

The structural lesson of the Shai-Hulud campaign across all three waves: the attack surface is not where the value is stored. It is where the value moves.

MITRE ATT&CK mapping

TacticTechniqueWhere it shows up
Initial AccessT1195.002 — Compromise Software Supply ChainThe Checkmarx-derived dev tool that landed on maintainer infrastructure
Credential AccessT1552.001 — Credentials in FilesWorm reads .npmrc, .aws/credentials, .ssh/, shell history, MCP configs
Persistence / Privilege EscalationT1078 — Valid AccountsStolen npm publish token used to ship a fully-signed, valid release
ExfiltrationT1567 — Exfiltration Over Web ServiceCollected credentials pushed to public GitHub repositories

Cremit Analysis

Three NHI Kill Chain stages line up precisely with what made this incident possible. None of them are about a vulnerability in cryptography or a zero-day in a runtime — they are about how organizations operate identities over time.

Ghost Key. The npm publish token used to ship @bitwarden/cli is a Non-Human Identity. Like every NHI, it has no face attached to it — no Slack handle to ping when something looks off, no laptop to wipe when its owner leaves. When that token was used by the attacker, the publish event from a different runner in a different timeframe almost certainly looked statistically similar to a legitimate release.

Drifted Key. Publish tokens accumulate scope and reach over time. A token originally minted to ship a single internal tool can end up publishing to a top-level public scope years later, often without anyone reviewing whether the original constraints still hold. The further a key drifts from its original purpose, the larger the blast radius when it is finally captured.

Unattributed Key. The worm's payload exfiltrated cloud tokens from CI runners. In most organizations, those tokens are not mapped to a specific workload, service owner, or rotation policy. When the leak is detected, the rotation playbook becomes archaeology — you have to figure out what the token does before you can safely revoke it. That delay is the campaign's oxygen.

The NHI Severity Index score of 9.0 reflects ecosystem-wide blast radius (any pipeline using @bitwarden/cli), production reachability (the worm targeted credentials at the source of where they live and move), and variable privilege levels depending on the credential.

The point of the kill chain framing is not to assign blame. It is to show that the same identity-management gaps that get exploited in slow, opportunistic attacks are also the gaps that get exploited in 90-minute supply chain bursts. They are the same problem — and they are exactly the problem Argus is built to surface, by indexing the public-facing surface of the developer ecosystem (public GitHub, package registries, paste sites) for credentials matching the customers it protects.


References

  1. [1]
    Bitwarden Statement on Checkmarx Supply Chain Incident
    primary·2026-04-23·community.bitwarden.com
  2. [2]
    Bitwarden CLI compromised in ongoing supply chain campaign
    reporting·2026-04-23·thehackernews.com
  3. [3]
    Bitwarden CLI npm package compromised to steal developer credentials
    reporting·2026-04-23·bleepingcomputer.com
  4. [4]
    Shai-Hulud campaign — Bitwarden CLI supply chain attack analysis
    analysis·2026-04-24·ox.security
  5. [5]
    Bitwarden npm package hit in supply chain attack
    reporting·2026-04-24·securityweek.com

Related incidents

2021-04-15·CRITICAL
Codecov Bash Uploader Compromise (2021)
2026-04-19·HIGH
Vercel Context.ai Incident: Environment Variables Accessed via Compromised AI Tool (2026)
last reviewed / 2026-04-25reviewer / benlicense / CC BY 4.0
// incident metadata
severity
CRITICAL9.0
status
confirmed
disclosed
2026-04-22
occurred
2026-04-22 → 2026-04-22
vector
npm supply chain
platforms
npmGitHubBitwardenAWSGCPAzure
tokens
npm Publish TokenGitHub PATAWS Access KeyGCP Service AccountAzure Service PrincipalSSH Private KeyEnvironment VariableAPI Key (generic)
nhi severity index
score9.0 / 10blast radiusecosystem-widereachabilityproductionprivilegevariable
nhi kill chain
Ghost Key↗Drifted Key↗Unattributed Key↗
metrics
exposure1 days