Bitwarden CLI compromised in ongoing Checkmarx supply chain campaign
TL;DR Highlight
Bitwarden CLI npm package delivers malware via GitHub Actions, stealing user credentials.
Who Should Read
Developers and DevOps engineers installing npm packages in CI/CD pipelines or using the Bitwarden CLI, especially teams automating dependency installation in GitHub Actions workflows.
Core Mechanics
- The affected version, @bitwarden/cli 2026.4.0, had malicious code inserted into the bw1.js file. Attackers compromised Bitwarden’s GitHub Actions CI/CD pipeline to inject the payload into build artifacts.
- This incident is part of the Checkmarx supply chain campaign—a series of attacks targeting the npm ecosystem—and shares the same C2 endpoint (audit.checkmarx[.]cx/v1/telemetry) and payload structure as previously analyzed mcpAddon.js.
- The malicious payload scrapes the memory of GitHub Actions Runners to steal GitHub tokens, AWS credentials from ~/.aws/ files and environment variables, Azure/GCP/npm tokens from azd·gcloud·~/.npmrc, and even Claude/MCP configuration files.
- Stolen npm tokens are used to find other npm packages with write access, injecting malicious code into the preinstall hook for redistribution. Public repositories on GitHub are also created with Dune novel-themed names ({word}-{word}-{3-digit number}) to commit encrypted results.
- A Russian locale killswitch causes the malware to silently exit if the system locale starts with 'ru', checking Intl.DateTimeFormat().resolvedOptions().locale and the LC_ALL, LC_MESSAGES, LANGUAGE, and LANG environment variables.
- Because the malicious payload executes during the npm install preinstall hook, existing security practices of scanning code after installation are ineffective. CI/CD environments with automated installation are particularly vulnerable due to short exposure windows.
- Impact was limited as the Bitwarden CLI does not auto-update, with approximately 334 downloads affected. Browser extensions, MCP servers, and other official distributions remain unaffected.
- The payload injects itself into ~/.bashrc and ~/.zshrc to maintain persistence after shell restarts, and incorporates ideological branding from Dune novels ('Shai-Hulud', 'Butlerian Jihad')—a departure from previous Checkmarx campaigns.
Evidence
- "Practical advice was shared that setting a minimum release age for npm package installations can defend against such attacks. Setting min-release-age=7 (days) in .npmrc (npm 11.10+) could have prevented this package (~19 hours to discovery/deprecation) and previous quickly-removed cases like axios and ua-parser-js."
How to Apply
- If using npm/pnpm/bun/uv, add a minimum release age to your package manager configuration. Set min-release-age=7 in ~/.npmrc, minimum-release-age=10080 (minutes) in pnpm rc, and minimumReleaseAge = 604800 (seconds) in ~/.bunfig.toml to prevent newly deployed malicious packages from automatically installing.
- In CI/CD pipelines, pin package versions in package.json without the ^ range and commit the lockfile. For critical tools like Bitwarden CLI, always pin versions.
- If currently using Bitwarden CLI, check CI logs for use of the affected version (2026.4.0) and immediately rotate any secrets (GitHub tokens, AWS/GCP/Azure credentials, npm tokens, SSH keys) potentially exposed in that workflow. Refer to the Bitwarden community for the timeframe of compromise.
- If using GitHub Actions, pin third-party Action versions to SHA hashes and remove unnecessary secret access permissions to minimize the blast radius of a compromise.
Code Example
snippet
# ~/.npmrc (npm 11.10+ required)
min-release-age=7 # Unit: days
# ~/Library/Preferences/pnpm/rc
minimum-release-age=10080 # Unit: minutes
# ~/.bunfig.toml
[install]
minimumReleaseAge = 604800 # Unit: seconds
# ~/.config/uv/uv.toml (Python uv package manager)
exclude-newer = "7 days"Terminology
Supply Chain AttackAn attack that compromises your software by targeting the libraries or build tools you use, rather than your own code. It's like hacking a food supplier to contaminate restaurant meals.
C2 (Command & Control)The server that malware uses to receive commands from attackers and send stolen data. It acts as the headquarters for the malicious program.
preinstall hookA script that automatically runs before package installation during npm install. Configured in package.json, it allows attackers to execute malicious code without the user being able to prevent it.
Version PinningSpecifying a package version exactly (e.g., '1.2.3') instead of using a range (e.g., '1.x.x'). Using a range can allow malicious updates to be automatically installed.
CI/CD PipelineAn automated process for building, testing, and deploying code. GitHub Actions is a popular example, and compromising this pipeline can contaminate the software being deployed.
Kill SwitchA mechanism that causes malware to stop running under certain conditions. In this case, it exits if the system locale starts with 'ru'.
Related Resources
- Original Article: Bitwarden CLI Compromised in Ongoing Checkmarx Supply Chain Campaign
- Bitwarden Official Statement
- rbw: A Bitwarden CLI alternative written in Rust
- DepsGuard: Package Manager Security Configuration Helper
- Cooldowns.dev: Package Release Cooldown Setting Tool
- The Install Was the Attack (AgentSH Blog)