# A Mini Shai-Hulud Has Appeared: Obfuscated Bun Runtime Payloads Hit SAP-Related npm Packages

Shai-Hulud npm worm compromised SAP-ecosystem packages via preinstall hooks, downloading Bun to run an obfuscated credential stealer that self-propagates through stolen npm tokens.

- Payout: Real-world hack
- Severity: critical
- Program: SAP
- Analysis by: StepSecurity
- Disclosed: 2026-05-04
- Write-up quality: 9/10
- Original: https://www.stepsecurity.io/blog/a-mini-shai-hulud-has-appeared
- Library page: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared
- Tags: area:oss domain:oss impact:data-leak impact:mass-exploit kind:incident platform:threat-intel sev:critical tech:github-actions tech:nodejs technique:source-review vuln:secrets-leak

**Target:** npm packages (mbt, @cap-js/sqlite, @cap-js/postgres, @cap-js/db-service) and GitHub Actions runners
**Root cause:** Compromised npm automation token and abused OIDC trusted publishing (repo-wide trust) let attacker publish packages with a preinstall hook that downloads Bun and executes an 11.6MB obfuscated stealer.
**Steps:**
1. Attacker obtains npm token for mbt or compromises SAP dev GitHub account to push to update/releases branch in cap-js/cds-dbs
2. Modify release-please.yml to fire on non-main branch and print double-base64-encoded npm token via OIDC exchange
3. Publish package version with `"preinstall": "node setup.mjs"` in package.json
4. setup.mjs downloads Bun v1.3.13 from GitHub Releases and runs `execution.js` under Bun to evade EDR
5. Payload checks locale (exits if ru), daemonizes on dev machines, runs inline in CI
6. Harvests npm/AWS/GCP/Azure/GitHub tokens; on GitHub Actions Linux, dumps Runner.Worker memory via `/proc/{pid}/mem` and regex `"([^"]+)":{"value":"([^"]*)","isSecret":true}`
7. Encrypts stolen data AES-256-GCM, wraps key with embedded RSA-4096, commits to dead-drop repo named `<dune-adj>-<dune-noun>-<num>` on victim account
8. Uses stolen npm tokens to enumerate org packages and PUT hand-rolled publish bodies to registry.npmjs.org to propagate
9. Injects `.vscode/tasks.json` (runOn folderOpen) and `.claude/settings.json` (SessionStart hook) into accessible repos for persistence
**How found:** StepSecurity's OSS AI Package Analyst and Harden-Runner detected the compromise within minutes of first malicious publish; runtime trace in audit mode captured node->bun->python process chain and /proc memory access.
**Exploitation:** Worm installs via npm preinstall, steals npm tokens and cloud creds, self-publishes to all reachable packages, and persists via IDE/Claude Code hooks in victim repos; exfiltrates encrypted blobs to public GitHub dead-drop repos on victim accounts.
**Escalation:** Chains npm token theft to org-wide package publishing, GitHub token to workflow injection stealing all repo secrets, and IDE hooks to re-infect every developer who opens the repo.
**Insight:** npm trusted publishing configured at repo level (not branch/workflow) lets any branch push mint publish tokens; also, GitHub Actions runners share UID with Runner.Worker so /proc/{pid}/mem dumps bypass secret masking — check for repo-wide OIDC trust and monitor for non-node child processes during install.
