May 04, 2026 · 9 min read
The npm Worm That Hit SAP Last Week Is the First One That Hides Inside Your Claude Code Settings
On the morning of April 29, 2026, between 09:55 and 12:14 UTC, four malicious npm packages went live with 572,000 combined weekly downloads. The payload was 11.6 megabytes, ran on the Bun JavaScript runtime instead of Node, exfiltrated AES-256 encrypted credentials, and—in a first for supply chain attacks—planted persistence by editing the configuration files for Claude Code and VS Code.
Four Packages, Two Hours, 572,000 Weekly Installs
The compromised packages all live in SAP's Cloud Application Programming model—the framework SAP enterprise developers use to build cloud applications on top of HANA databases. The four versions that were poisoned, per The Hacker News reporting:
mbt@1.2.48@cap-js/db-service@2.10.1@cap-js/postgres@2.2.2@cap-js/sqlite@2.2.2
Combined weekly downloads sit at 572,000, per The Register's coverage. SAP confirmed the compromised versions were pulled from npm within hours, but every CI/CD pipeline, developer machine, and Docker build that resolved one of those versions during the attack window now needs to be treated as suspect.
Researchers from Wiz, Aikido Security, Onapsis, and Socket all independently flagged the campaign within 24 hours and attributed it to TeamPCP—the same crew responsible for the Bitwarden CLI and Checkmarx attacks the previous week, the Telnyx wav malware Python package, and an Aqua Security Trivy compromise from March.
The Bun Runtime Trick
When a developer runs npm install on a poisoned version, the malicious preinstall hook fires a small loader called setup.mjs. That loader does something most npm malware doesn't: it downloads Bun, an alternative JavaScript runtime, and uses Bun—not Node—to execute the 11.6 MB credential stealer (execution.js).
This is a deliberate evasion. Most enterprise endpoint security and Node.js hardening tools watch what Node spawns. They have no signature for Bun behavior. The runtime has perfect parity with Node for most JavaScript code, so the malware runs transparently while sliding under monitoring tools that key off Node process trees.
The AI Assistant Persistence Move
Here is the part that makes this attack different from every prior npm worm. After running its credential theft pass, Mini Shai-Hulud writes two new files into the developer's workspace:
.claude/settings.json— abuses Claude Code'sSessionStarthook so the malicious payload runs every time the developer opens an AI coding session..vscode/tasks.json— registers a malicious VS Code task that executes when the developer next opens the folder.
Both files are routine artifacts in modern developer workflows. .claude/settings.json is the per project configuration for Anthropic's Claude Code agent. .vscode/tasks.json is the file that defines build commands for the most widely used code editor on Earth. Both regularly land in git commits—and once they do, anyone who clones the repository inherits the persistence.
The implication for a development team is grim. A single developer who installs @cap-js/postgres at the wrong moment commits a poisoned .vscode/tasks.json at the next push. Every teammate who pulls and opens the workspace runs the malware again. CI runners that pull the repo run it. Reviewers who clone it locally run it. The blast radius scales with the team's velocity.
What Mini Shai-Hulud Steals
The credential stealer harvests, in a single pass:
- GitHub tokens and npm tokens from local config files
- GitHub Actions secrets when running inside a CI runner (extracted from runner memory)
- AWS, Azure, GCP, and Kubernetes credentials from local credential files and shell environment variables
- Browser passwords from Chrome, Safari, Edge, Brave, and Chromium—a new capability introduced in this generation
- Local SSH keys and dotfiles
- AI coding tool config: Claude Code settings and any MCP server configurations the developer has registered
The exfiltration pipeline is also a step up from the original Shai-Hulud. The harvested data is encrypted with AES-256-GCM, the symmetric key is encapsulated with RSA-4096, and the ciphertext gets pushed to a fresh GitHub repository created from the victim's own account using their stolen GitHub token. The repositories follow a recognizable naming pattern—"A Mini Shai-Hulud has Appeared"—and researchers had identified over 1,100 such repos within 48 hours of the attack going live.
It Refuses to Run on Russian Computers
Before any of the credential theft fires, the malware checks the system locale. If the host machine is configured for the Russian language, execution.js exits cleanly without exfiltrating anything. This is the standard "do not steal from your home country" check that Russian aligned criminal groups have used for years to avoid prosecution under domestic laws that don't extend to cybercrime against foreign targets.
The locale check is not, by itself, attribution. But combined with the rest of TeamPCP's tooling chain—the Russian language strings researchers have pulled from earlier samples, the operational hours that map to Moscow timezone, the targeting pattern—it pushes the geographic origin of the campaign into uncomfortable proximity.
Why SAP Was the Target
SAP CAP packages don't have the raw download numbers of axios or lodash. Half a million weekly downloads is modest by npm standards. What compensates for the smaller footprint is who installs them.
SAP is the system of record for finance, HR, and supply chain operations at a substantial fraction of the Fortune 1000. Anyone running npm install on @cap-js/postgres is, by definition, an enterprise SAP developer with access to financial data pipelines, employee records, or supplier relationships. The credentials harvested from that machine open doors into systems where a single stolen token might be worth more than ten thousand consumer infections.
This is the same shift in supply chain economics that pushed the North Korea backdoored axios incident earlier this year and the Mercor LiteLLM AI startup compromise: attackers are no longer chasing volume. They're chasing surface area against high value enterprise targets.
What Developers Should Do Now
If your environment installed any of the compromised SAP CAP versions on April 29, treat the developer machine and any CI runner that touched them as compromised. The remediation list, condensed from Wiz, Onapsis, and Socket guidance:
- Search lockfiles, artifact stores, and CI logs for
mbt@1.2.48,@cap-js/db-service@2.10.1,@cap-js/postgres@2.2.2, and@cap-js/sqlite@2.2.2. - Rotate everything that touched a compromised machine: GitHub PATs, npm tokens, AWS/Azure/GCP keys, Kubernetes service account tokens, GitHub Actions secrets, and any cloud database credentials referenced from
.envfiles. - Audit your repos for new commits adding
.claude/settings.jsonor modifying.vscode/tasks.json. The malware adds these silently. A diff against your last clean commit will show them. - Search GitHub for repos titled "A Mini Shai-Hulud has Appeared" attached to any of your team's accounts. If you find one, the corresponding GitHub token is compromised.
- Reinstall browsers on any machine that ran the payload. Saved passwords in Chrome, Safari, Edge, Brave, and Chromium were pulled in the first 30 seconds of execution.
- Audit MCP server configurations. Any MCP endpoints registered in your AI coding tools were exposed; the credentials those servers proxy should be rotated too.
The Trend Is the Story
Mini Shai-Hulud is significant not because of what it stole on April 29 but because of what it telegraphs about the next year of supply chain attacks. The pattern, in three lines:
- Targets are narrowing. Enterprise specific package ecosystems (SAP CAP, AI tooling, security vendors) are now the prize, not generic utilities.
- Persistence is moving to AI tooling. Claude Code config files, VS Code task definitions, MCP server registrations—the surface area developers added to their workflows in 2025 is now part of the attack surface.
- Encryption is becoming standard. AES-256-GCM exfiltration with RSA-4096 key wrapping puts captured data outside the reach of automated scanners that try to detect leaked credentials in transit.
The same 11.6 MB payload could have been wrapped around any other enterprise focused npm package. The compromise was working as designed—the only reason it shut down at 12:14 UTC was that detection ran ahead of TeamPCP's plans by a few hours. The next iteration will not give security researchers the same window.