Fake Bitwarden CLI package stole credentials and backdoored other packages
TL;DR - @bitwarden/[email protected] is a malicious impersonator. Its preinstall script bootstraps the Bun runtime (v1.3.13), then runs a large obfuscated payload that harvests cloud credentials, CI/CD secrets, npm tokens, and SSH keys. If it finds a usable npm token, it downloads packages that identity can publish, injects a new preinstall hook, and republishes them - spreading the infection automatically.
What happened
Unit 42 published a threat-research write-up on npm supply chain attacks, including detailed analysis of a malicious package impersonating Bitwarden's CLI tool - @bitwarden/[email protected].
The attack chain is tight. A preinstall lifecycle script runs a bootstrapper (bw_setup.js) that detects OS and architecture, downloads the Bun runtime (v1.3.13) directly from Bun's official GitHub releases, then executes the main payload (bw1.js). That payload is a heavily obfuscated, multi-megabyte JavaScript file that bundles multiple SDKs and provider-specific credential collectors.
Unit 42 documents the harvesting targets: cloud credentials (AWS, Azure, Google Cloud), CI/CD secrets, npm tokens, GitHub PATs, and SSH keys from developer workstations and CI runners. Once the payload finds a usable npm token, it shifts from theft to propagation. It downloads tarballs of packages that token can publish, injects a new preinstall hook - for example "preinstall": "node setup.mjs" - and republishes the trojanised versions under the stolen identity.
Unit 42 also documents the command-and-control infrastructure: a C2 domain at audit.checkmarx[.]cx and a fallback mechanism using the GitHub Search API as a dead drop.
This is not a "one compromised package" incident. A single infected developer or CI runner with publish rights becomes a vector into every package that identity controls. The blast radius scales with token permissions, not with how many people installed the original malicious version.
| Item | Detail |
|---|---|
| Malicious package | @bitwarden/[email protected] |
| Execution trigger | preinstall lifecycle script |
| Downloaded runtime | Bun v1.3.13 |
| Reported behaviour | Credential harvesting + worm-like propagation via republished backdoored packages |
| C2 domain | audit.checkmarx[.]cx |
| Fallback mechanism | GitHub Search API used as dead drop |
Who is impacted
- Teams and developers who installed
@bitwarden/[email protected]during the exposure window Unit 42 describes. - Organisations whose developer workstations or CI runners allow npm lifecycle scripts (
preinstall/postinstall) to execute during dependency install. - Any environment holding high-value secrets in environment variables or local config - cloud credentials, npm tokens, GitHub tokens, SSH keys.
- Highest risk: maintainers with npm publish rights. Unit 42 describes automated backdooring and republishing of packages using stolen tokens, meaning a single compromised identity can propagate the payload across multiple packages.
What to do now
- Scope your exposure first. Check whether any developer workstation, CI runner, or build environment pulled
@bitwarden/[email protected]during the window Unit 42 identifies. Check npm lockfiles, build logs, and container image history. - Rotate every credential that may have been in scope. Unit 42 explicitly names: npm tokens, GitHub PATs, AWS/Azure/Google Cloud keys, SSH keys, and CI/CD secrets. Rotate them all, do not try to guess which ones were captured.
- Hunt for propagation in packages you maintain:
- unexpected version bumps or newly added
preinstalllifecycle scripts in any package your identities can publish - unexpected workflow files, artifact downloads, or new repository activity in GitHub orgs connected to affected tokens
- new or modified files named
setup.mjsor similar bootstrapper patterns in your package source
- unexpected version bumps or newly added
- Apply ecosystem hardening controls Unit 42 recommends:
- add
ignore-scripts=trueto.npmrcto disable lifecycle scripts during install - use
package-lock.jsonandnpm ciin CI pipelines to reduce dependency drift - enforce a cooldown period before allowing newly published package versions (blocking versions published in the last 24-72 hours)
- route npm traffic through a private registry or proxy instead of directly hitting
registry.npmjs.org
- add
- Follow Bitwarden, npm, and your internal IR playbooks for any additional scoping and response steps specific to your environment.
Related
Content is AI-assisted and reviewed by our team, but issues may be missed and best practices evolve rapidly, send corrections to [email protected]. Always consult official documentation and validate key implementation decisions before making design or security choices.
