JustAppSec
Back to news

Malicious preinstall hook in SAP CAP packages runs credential stealer

2 min readPublished 29 Apr 2026Updated 29 Apr 2026Source: Aikido Security Blog

TL;DR - Malicious releases of @cap-js/sqlite, @cap-js/postgres, @cap-js/db-service, and mbt added "preinstall": "node setup.mjs" to their package.json. That hook downloads Bun 1.3.13 from GitHub and uses it to run an obfuscated 11.7MB credential stealer during npm install. If you ran npm install with any of these versions, treat your secrets as compromised.

What happened

The @cap-js packages provide database adapters for SAP Cloud Application Programming Model. mbt is the SAP MTA Build Tool. Both sit directly in developer and CI/CD workflows - which made them a worthwhile target.

Somebody published poisoned releases of all four. Each had two new files injected: setup.mjs and execution.js. The package.json was modified to add a preinstall lifecycle hook:

"scripts": { "preinstall": "node setup.mjs" }

When npm install runs, Node executes setup.mjs before the package is even installed. That script fetches a platform- and architecture-specific Bun 1.3.13 binary from github.com/oven-sh/bun/releases/download/bun-v1.3.13/..., then uses it to run execution.js - the 11.7MB obfuscated payload.

The payload casts a wide net. Aikido reports it targets:

  • GitHub and npm tokens
  • GitHub Actions secrets
  • Cloud provider credentials across AWS, Azure, GCP, and Kubernetes
  • Local developer tool configs and kubeconfigs

Exfiltration routes through attacker-controlled GitHub repositories. Encrypted results are written to paths like results/results-<timestamp>-<counter>.json inside repos with the description A Mini Shai-Hulud has Appeared.

This is install-time compromise in packages that developers and CI runners pull routinely. No user interaction beyond npm install is required.

Who is impacted

Anyone whose environment installed one of these specific versions - developer laptops, CI runners, build images, caches.

PackageCompromised version
@cap-js/sqlite2.2.2
@cap-js/postgres2.2.2
@cap-js/db-service2.10.1
mbt1.2.48

Highest risk environments:

  • CI/CD runners where GitHub Actions secrets, cloud credentials, and deploy keys are in scope during builds.
  • Developer workstations with gh auth configured, .npmrc tokens, kubeconfigs, or local cloud CLI credentials.

What to do now

  • Hunt for the compromised versions across lockfiles, caches, build artefacts, and install logs:

  • If any affected version was installed, rotate secrets immediately. Don't limit rotation to npm tokens. The payload targets GitHub, npm, cloud providers (AWS, Azure, GCP), Kubernetes, CI secrets, and local developer tooling. Rotate everything reachable in the environments that ran the install.

  • Check for GitHub-side indicators Aikido identified:

    • Commit marker string OhNoWhatsGoingOnWithGitHub used as a dead-drop in commit messages
    • Repositories with description A Mini Shai-Hulud has Appeared
    • Commits titled chore: update dependencies authored by claude <[email protected]>
    • Unexpected files: .vscode/tasks.json, .vscode/setup.mjs, .claude/setup.mjs, .claude/execution.js, .claude/settings.json
    • Exfiltration result paths: results/results-<timestamp>-<counter>.json
  • Work your standard build-time compromise playbook:

    • Identify which runners and developer endpoints executed the affected install
    • Inventory which credentials were reachable in those environments
    • Rotate or revoke each credential via its provider's process
    • Review GitHub Actions logs and repository audit trails for unexpected writes matching the patterns above

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.

Need help?Get in touch.