Today Socket Research Team published a report that needs to be in your queue: four SAP CAP npm packages were compromised with malicious preinstall scripts. Combined, those packages account for 572,000 weekly downloads. The script downloaded and executed a Bun binary from GitHub Releases. On Windows, it used PowerShell with -ExecutionPolicy Bypass.
Affected packages:
-
mbt@1.2.48— 52,000 weekly downloads -
@cap-js/db-service@2.10.1— 260,000 weekly downloads -
@cap-js/postgres@2.2.2— 10,000 weekly downloads -
@cap-js/sqlite@2.2.2— 250,000 weekly downloads
The @cap-js namespace is the official SAP Cloud Application Programming Model runtime — these are the core database and service layers for SAP BTP cloud native apps.
What the preinstall hook actually did
npm's preinstall lifecycle script runs before your code does anything. Before lockfile validation. Before any scanner. The attacker's script:
- Detected the current operating system
- Downloaded a platform-specific Bun ZIP from a GitHub Releases URL (following HTTP redirects without validation)
- Extracted and immediately executed the Bun binary
- On Windows: used
PowerShell -ExecutionPolicy Bypassto skip execution policy restrictions
GitHub Releases was the delivery server — most corporate firewalls allow github.com traffic.
Why AI coding agents make this worse
If you use Claude Code, Cursor, or any agentic coding tool that runs terminal commands, pay attention here.
Agents don't review preinstall scripts before executing. When an AI agent scaffolds a new SAP BTP service, it runs npm install as a standard step. It doesn't pull up the preinstall field from each dependency's package.json and ask for approval. No agent does this by default.
Agents run with your full credential surface. AI coding agents run in your shell — they can access your .env files, ~/.aws/credentials, SSH keys, Git tokens. A preinstall script in that same environment has identical access.
Agent logs get less scrutiny. A malicious preinstall script that succeeds and exits cleanly blends into normal npm install output. In a CI/CD log, that output gets reviewed on failure, not success.
What to do right now
Check your exposure
npm ls mbt @cap-js/db-service @cap-js/postgres @cap-js/sqlite
# Check lockfile for specific malicious versions:
grep -E '"(mbt|@cap-js/db-service|@cap-js/postgres|@cap-js/sqlite)"' package-lock.json
If you installed any affected version today (April 29, 2026): treat that machine as compromised. Rotate credentials. Audit cloud provider access logs.
Switch CI/CD to npm ci
# Uses package-lock.json exactly, fails on mismatch:
npm ci
# For audit steps, prevents preinstall execution:
npm install --ignore-scripts
Gate your AI agent's package installations
Add this to your agent's system prompt:
Before running npm install with any package version published in the last 24 hours,
require explicit user approval and show the scripts field from that package's
package.json first.
The bigger pattern
This is the fourth npm supply chain incident in eight weeks on LucidShark's radar. All four malicious versions were published in a short synchronized window — suggesting a compromised CI/CD pipeline or npm publishing token from the legitimate SAP publisher account. When the legitimate publisher is compromised, checking package scope and publisher identity provides no protection.
The defense layer that catches this: runtime script analysis (like Socket.dev) that inspects what lifecycle scripts do before you run them. That layer needs to be inside your AI coding agent's decision loop — not just in your CI/CD pipeline.
Full technical writeup with the complete remediation checklist: lucidshark.com/blog/sap-cap-npm-supply-chain-preinstall-attack-2026
Top comments (0)