Two Attack Vectors That Bypass Your npm Security: Lessons from Bitwarden's 90-Minute Nightmare
The recent @bitwarden/cli compromise wasn't just another supply chain attack—it was a masterclass in how attackers exploit two fundamentally different attack vectors that most security tooling completely misses.
For 90 minutes on April 22, 2026, anyone running npm install @bitwarden/cli pulled down a weaponized package that could steal AWS tokens, GitHub PATs, SSH keys, and even propagate itself through your CI/CD pipelines. But here's what makes this incident particularly instructive: it demonstrates two distinct attack patterns that require completely different detection strategies.
The Dual Attack Pattern
Most discussions focus on what was stolen, but the real insight lies in how the attack succeeded through two complementary vectors:
Vector 1: CI/CD Workflow Injection
Attackers didn't compromise Bitwarden's npm account or steal maintainer credentials. Instead, they injected malicious GitHub Actions workflows that bypassed code review entirely. The tampered workflow automatically published the poisoned package to npm during Bitwarden's normal release process.
Vector 2: Runtime Package Tampering
Once installed, the package executed a sophisticated payload (bw1.js) that didn't just steal credentials—it turned infected machines into propagation nodes, creating new malicious packages and injecting workflows into other repositories.
<> "This fits a pattern of CI/CD compromises bypassing code review via malicious workflows"—and it's why traditional package scanning often fails./>
Why Your Security Tools Missed This
The conventional wisdom says "scan your dependencies" and "use lockfiles." But this attack reveals why that's insufficient:
1// Your package-lock.json looked perfectly normal
2{
3 "@bitwarden/cli": {
4 "version": "2026.4.0",
5 "resolved": "https://registry.npmjs.org/@bitwarden/cli/-/cli-2026.4.0.tgz",
6 "integrity": "sha512-[legitimate-looking-hash]"
7 }
8}The package came from the official registry, with proper signatures, published by the legitimate maintainer account. Static analysis tools that check for known malicious patterns wouldn't flag it because the malicious code was fresh and campaign-specific.
More critically, the workflow injection happened upstream in Bitwarden's CI/CD process. No amount of downstream scanning would catch a compromise that happens during the legitimate build process.
The Worm Behavior That Changes Everything
What makes this particularly dangerous is the self-propagating "worm" behavior. Once installed, the malicious package:
1. Harvested credentials from environment variables, config files, and running processes
2. Used stolen GitHub tokens to inject malicious workflows into other repositories
3. Republished packages with preinstall hooks using stolen npm tokens
4. Exfiltrated data to Dune-themed GitHub repositories with markers like LongLiveTheResistanceAgainstMachines
This means a single installation could compromise your entire organization's CI/CD infrastructure, not just the machine where it was installed.
1# If you see this in your CI logs between 5:57-7:30 PM ET on April 22, 2026
2npm install @bitwarden/cli@2026.4.0
3# Assume all credentials on that system are compromisedTwo Detection Strategies for Two Attack Types
The key insight is that you need different detection mechanisms for each attack vector:
For Workflow Injection Attacks:
- Audit GitHub Actions permissions: Look for unexpected
id-token: writepermissions - Monitor workflow changes: Set up alerts for modifications to
.github/workflows/ - Use minimal permissions: Default to
permissions: read-alland explicitly grant only what's needed - Enable OIDC authentication: This creates an audit trail for publish operations
1# Hardened workflow example
2name: Publish
3on:
4 release:
5 types: [published]
6jobs:
7 publish:
8 runs-on: ubuntu-latest
9 permissions:
10 contents: read
11 packages: write
12 # Only add id-token: write if you actually need OIDC
13 steps:
14 # Your publish steps hereFor Runtime Package Tampering:
- Runtime monitoring: Tools like Socket that analyze behavior during installation
- Network monitoring: Watch for unexpected outbound connections during npm install
- Process monitoring: Alert on credential file access during package installation
- Lockfile enforcement: Pin exact versions in CI/CD
<> The harsh reality: Traditional security scanning focuses on known vulnerabilities, but supply chain attacks exploit the trust model itself./>
Your 10-Minute Action Plan
If you're using @bitwarden/cli in any capacity:
1. Check your logs immediately for any installation of version 2026.4.0
2. Rotate all secrets if you find a match: AWS keys, GitHub PATs, npm tokens, SSH keys
3. Pin to version 2026.4.1 or stick with the last clean version (2026.3.0)
4. Audit your CI/CD workflows for unexpected modifications
5. Look for Dune-themed repositories in your GitHub organization (signs of worm propagation)
1# Emergency remediation
2npm install @bitwarden/cli@2026.4.1
3# or
4npm install @bitwarden/cli@2026.3.0Why This Matters Beyond npm
This attack pattern isn't unique to npm—it's the new reality for any ecosystem with automated publishing (PyPI, RubyGems, Docker Hub). The combination of CI/CD compromise and runtime propagation creates a "blast radius" far beyond the initial target.
The Bitwarden incident lasted only 90 minutes, but that was enough time for the malicious package to propagate globally. In our interconnected development world, 90 minutes might as well be 90 days.
The real lesson isn't about better scanning tools—it's about designing systems that assume compromise. Because in a world where legitimate packages can become malicious through no fault of their maintainers, paranoia isn't just healthy, it's essential.

