Lyrie
Supply-Chain-Post-Mortem Deep-Dive
0 sources verified·9 min read
By Lyrie.ai Cyber Research Division·5/5/2026

TL;DR

On April 29, 2026, attackers compromised four official SAP npm packages — mbt, @cap-js/db-service, @cap-js/sqlite, and @cap-js/postgres — reaching a combined 2.2 million monthly downloads. Each poisoned release shipped a preinstall hook that silently downloaded the Bun JavaScript runtime and executed an 11.6 MB obfuscated credential stealer. The malware vacuumed AWS, Azure, GCP, and GitHub tokens from developer workstations and CI runners, then exfiltrated them to 1,200+ public GitHub repositories created on victims' own accounts. The worm tagged its handiwork with the phrase "A Mini Shai-Hulud has Appeared." SAP and the security community detected the campaign in under ten minutes per package, but a three-to-four hour exposure window was enough to compromise an unknown number of enterprise developer environments. No CVE or GHSA record had been assigned at time of discovery.


Background: The Shai-Hulud Franchise

The name is borrowed from Frank Herbert's Dune — Shai-Hulud, the great sandworm that consumes everything in its path. In the npm threat landscape it has become a brand, an adversary flexing a repeating methodology across campaigns.

The original Shai-Hulud appeared in September 2025, targeting @ctrl/tinycolor, ngx-bootstrap, ng2-file-upload, and a cascade of their dependents. That campaign demonstrated the same core playbook: compromise a maintainer account, publish a malicious minor bump, trigger execution via an install hook, exfiltrate tokens to attacker-controlled GitHub repos. Snyk documented it extensively at the time.

A Bitwarden variant in early 2026 recycled the dead-drop-to-GitHub exfiltration technique against @bitwarden/[email protected], this time specifically hunting ghs_ (GitHub Actions scoped tokens) and deploying to CI pipelines. OX Security identified real user data leaked in that incident.

"Mini Shai-Hulud" — April 29, 2026 — represents the third documented campaign in this franchise, now pivoting squarely into the SAP enterprise developer supply chain.

The actor (identified as TeamPCP in Wiz's analysis) appears to be continuing an iterative development cycle: each campaign introduces new evasion tactics while keeping the core dead-drop-to-GitHub exfiltration architecture intact.


Technical Analysis

The Targeted Packages and Their Blast Radius

All four packages are central to SAP Cloud Application Programming Model (CAP) — the de facto framework for custom development on SAP Business Technology Platform, S/4HANA extensions, XSA applications, Fiori backends, and MTA-based deployments:

| Package | Malicious Version | Weekly Downloads | Monthly Downloads |

|---|---|---|---|

| mbt (Cloud MTA Build Tool) | 1.2.48 | ~52,000 | ~215,000 |

| @cap-js/db-service | 2.10.1 | ~260,000 | ~1,100,000 |

| @cap-js/sqlite | 2.2.2 | ~250,000 | ~1,000,000 |

| @cap-js/postgres | 2.2.2 | ~10,000 | ~32,000 |

Total affected monthly downloads: 2.2M+

SAP CAP packages sit inside nearly every package.json in enterprise SAP JavaScript development. Version ranges like "@cap-js/sqlite": "^2" pull the latest minor automatically — the exact mechanism exploited here.

Attack Execution Timeline (UTC, April 29 2026)

The campaign unfolded with surgical speed:

  • 09:55:25[email protected] published via the cloudmtabot npm account (account appears to have been hijacked or belongs to a disgruntled/former contributor)
  • 10:01:07 — First victim dead-drop repository appears on GitHub (repository gruposbftechrecruiter/siridar-navigator-935), confirming at least one developer installed and ran the package within 6 minutes of publication
  • 11:25:47@cap-js/[email protected] published
  • 12:03–12:04 — StepSecurity files coordinated disclosure issues on the SAP/cap-js GitHub repositories; independent researcher longieirl files a third disclosure at 14:02
  • 12:14:00@cap-js/[email protected] and @cap-js/[email protected] published
  • 13:31 — SAP maintainer chgeh acknowledges the issue, confirms remediation underway
  • 13:46 — SAP publishes clean post-incident versions via GitHub Actions OIDC trusted publisher
  • 14:02:50 — SAP engineer files PR #1592 gating npm publish behind manual approval
  • 15:40 — Clean [email protected] published, superseding malicious version

Note: [email protected] remained the latest dist-tag for mbt for several hours after the other packages were remediated, meaning bare npm install mbt continued resolving to the malicious tarball during that window.

The Preinstall Hook Vector

The attack exploits a fundamental npm feature: preinstall scripts in package.json execute automatically during npm install, before any developer inspects or audits the package's content. There is no default opt-out.

The malicious preinstall hook performs two steps:

1. Downloads the Bun JavaScript runtime (a self-contained, high-performance JS/TS runtime) from the official Bun GitHub Releases CDN. Using Bun rather than Node.js is deliberate: most security monitoring tools and SIEM integrations observe Node processes, not Bun. The download itself is indistinguishable from a legitimate developer fetching a build tool.

2. Executes an ~11.6 MB obfuscated payload using the freshly downloaded Bun binary. The payload is not a shell script — it is a compiled, heavily obfuscated JavaScript bundle that StepSecurity needed full deobfuscation effort to reverse.

This "bring your own runtime" evasion tactic is notable. By sidestepping the Node.js process tree, the attacker undermines endpoint detection rules keyed to node spawning suspicious child processes.

Payload Capabilities: A Full-Spectrum Credential Sweep

Once executed, the Shai-Hulud payload conducts an exhaustive credential harvest across the victim environment:

Developer workstation targets:

  • NPM auth tokens (~/.npmrc)
  • GitHub personal access tokens (~/.config/gh/hosts.yml, ~/.gitconfig)
  • SSH private keys (~/.ssh/)
  • AWS credentials (~/.aws/credentials, ~/.aws/config)
  • Azure CLI tokens (~/.azure/)
  • GCP service account keys (~/.config/gcloud/)
  • Environment variables (entire process.env dump)
  • Kubernetes kubeconfig (~/.kube/config)

CI/CD runner targets (elevated priority):

When the malware detects execution inside a GitHub Actions Linux runner, it enters a high-value harvest mode. It pipes input into sudo python3, strips NUL bytes, and scans for JSON-shaped lines containing ACTIONS_RUNTIME_TOKEN, GITHUB_TOKEN, and other workflow secrets injected into the runner environment. This escalation path turns a single compromised pipeline into an enterprise-wide credential sweep.

Russian language evasion:

The payload checks the host locale. If Russian language is configured, execution halts entirely — a strong indicator of nation-state alignment or at minimum a Russian-speaking threat actor protecting domestic systems.

Exfiltration Architecture: GitHub as Dead-Drop

The stolen data is processed through a three-stage encryption envelope:

1. Gzip compression of the raw secrets JSON

2. AES-256-GCM encryption with a per-execution symmetric key

3. RSA-OAEP wrapping of the symmetric key against an attacker-embedded public key

This wrapped bundle is committed to a newly created public GitHub repository on the victim's own account, under a results/ directory with a timestamped filename. The repository description is set to "A Mini Shai-Hulud has Appeared."

This architecture is elegant in its brutality:

  • GitHub's infrastructure handles availability — no attacker C2 server to take down
  • The data is technically "public" on the victim's account, normalizing the repository creation noise in GitHub audit logs
  • The attacker needs only their embedded RSA private key to decrypt any collected blob
  • The proliferation of these repositories with a consistent description string made them trivially searchable on GitHub — OX Security identified 1,200+ such repositories within hours of discovery

IOCs

| Type | Indicator |

|---|---|

| Malicious npm package | [email protected] |

| Malicious npm package | @cap-js/[email protected] |

| Malicious npm package | @cap-js/[email protected] |

| Malicious npm package | @cap-js/[email protected] |

| npm account (likely hijacked) | cloudmtabot |

| GitHub repo description (dead-drop identifier) | A Mini Shai-Hulud has Appeared |

| GitHub repo path pattern | */results/<timestamp>.json |

| Bun download source | https://github.com/oven-sh/bun/releases/ (legitimate binary, weaponized delivery) |

| SAP Security Note | 3747787 |

| Snyk advisory | SNYK-JS-MBT-16321404 |

| Snyk advisory | SNYK-JS-CAPJSDBSERVICE-16321402 |

| Snyk advisory | SNYK-JS-CAPJSSQLITE-16321405 |

| Snyk advisory | SNYK-JS-CAPJSPOSTGRES-16321403 |

| Campaign attribution | TeamPCP (Wiz Research) |

| Locale evasion | Russian language (ru_*) → execution abort |

GitHub Search IOC (for incident response):

"A Mini Shai-Hulud has Appeared" in:description

Lyrie Take

The Mini Shai-Hulud campaign illustrates three converging trends that make the modern software supply chain systematically difficult to defend:

1. Franchise-model adversaries. TeamPCP is not a one-off. They built a reusable attack kit — Bun-based loader, GitHub dead-drop exfiltration, recursive self-propagation — and are deploying it in successive campaigns against high-download-count targets. Each iteration refines evasion: the move from Node to Bun shows active learning from prior detections. Organizations should track the TTP pattern across campaigns, not just individual IOCs.

2. Developer trust as the hardest attack surface. Developers inherently trust npm install. The entire workflow assumes packages are benign unless proven otherwise — a naive assumption that preinstall hooks exploit perfectly. Unlike a phishing email, there is no suspicious link to hover over, no unfamiliar sender to scrutinize. The attack is invisible in the normal developer workflow. Until the ecosystem mandates signed installs and explicit preinstall approval by default, this vector remains wide open.

3. "Your account as C2" is a paradigm shift. Exfiltrating to the victim's own GitHub account is not just clever evasion — it's a statement about trust model inversion. GitHub's trust store works against defenders: the repositories are created by authenticated accounts, using normal GitHub APIs, and contain valid (if encrypted) JSON files. DLP tools that monitor outbound traffic to unfamiliar endpoints will not trigger. Cloud SIEM rules watching for unusual destinations will miss it. The signal is structural (new repository creation spike, unusual commit from a developer machine at install time) not content-based.

Lyrie's autonomous behavioral detection layer addresses this class of attack precisely because it profiles process-level behavior at install time, flagging anomalous child-process spawning patterns, unexpected network egress during package installation, and repository creation events correlated with npm install execution windows — the three telltale signals of a preinstall-hook supply chain attack.


Defender Playbook

Immediate (if you installed affected packages April 29, 2026)

1. Treat the workstation as fully compromised. Rotate every credential stored on that machine: AWS IAM keys, GitHub tokens, NPM auth tokens, GCP service accounts, Azure SP credentials, Kubernetes configs, SSH keys.

2. Audit your GitHub account for repositories created around the installation time. Search for "A Mini Shai-Hulud has Appeared" in your repositories and across GitHub's public search.

3. Revoke GitHub Actions secrets for any pipeline that ran on the affected machine or used the compromised packages.

4. Upgrade immediately to: [email protected], @cap-js/[email protected], @cap-js/[email protected], @cap-js/[email protected].

5. File an incident report internally — treat this as a potential cloud-wide breach, not just a developer machine compromise.

Short-term (pipeline hardening)

6. Pin exact package versions in all package.json files, or use lockfile enforcement (npm ci over npm install). Floating ranges like ^2 are what this attack weaponized.

7. Enable npm audit in CI and fail builds on new high/critical advisories. Configure npm to reject unpublished packages in your lock file.

8. Block or alert on preinstall/postinstall script execution in your CI environment. Both GitHub Actions and most enterprise CI platforms support disabling npm lifecycle scripts: npm install --ignore-scripts. Evaluate this for build pipelines that don't require them.

9. Implement process-level monitoring on developer workstations and CI runners: alert on bun binary downloads during npm install, child process spawns from package manager contexts, and GitHub API repository-creation events from non-interactive sessions.

10. Adopt npm provenance attestations where maintainers support them. SAP's post-incident PR #1592 introduced manual approval gates on npm publish via OIDC trusted publishers — verify your critical vendors have adopted similar controls.

Structural (supply chain program)

11. Maintain a SBOM (Software Bill of Materials) for all production applications, with automated monitoring for new CVEs and compromise reports against your dependency tree.

12. Establish a vendor package watchlist for high-criticality dependencies (SAP CAP packages, cloud SDK components, authentication libraries). Subscribe to security advisories from Socket, Snyk, and OSV.

13. Run developer machines and CI runners in ephemeral, credential-isolated environments. A compromised ephemeral runner with a scoped, short-lived OIDC token is far less catastrophic than a developer laptop with years of cached cloud credentials.

14. For SAP environments specifically: Review SAP Security Note 3747787. Inventory all custom BTP applications, XSA projects, Fiori backends, and CAP-based integrations for exposure to affected package versions.


Sources

1. Snyk — "Bun-Based Stealer Hits SAP @cap-js and mbt npm Packages" (2026-04-30): https://snyk.io/blog/bun-based-stealer-hits-sap-cap-js-mbt-npm-packages/

2. OX Security — "Shai-Hulud Hits SAP: Stolen Credentials Found in 1,200 GitHub Repos" (2026-04-29): https://www.ox.security/blog/shai-hulud-sap-supply-chain-attack-npm/

3. Onapsis — "Emerging Supply Chain Attack (Mini Shai-Hulud) Targeting SAP CAP Ecosystem" (2026-04-30): https://onapsis.com/blog/sap-cap-mini-shai-hulud-supply-chain-attack/

4. StepSecurity — "A Mini Shai-Hulud Has Appeared: Obfuscated Bun Runtime Payloads Hit SAP npm Packages" (2026-04-29): https://www.stepsecurity.io/blog/a-mini-shai-hulud-has-appeared

5. Wiz Research — "Supply Chain Campaign Targets SAP npm Packages with Credential-Stealing Malware" (2026-04-29): https://www.wiz.io/blog/mini-shai-hulud-supply-chain-sap-npm

6. The Register — "Ongoing supply chain attacks worm into SAP npm packages" (2026-04-30): https://www.theregister.com/2026/04/30/supply_chain_attacks_sap_npm_packages/

7. SAP Security Note 3747787: https://me.sap.com/notes/3747787/E

8. Snyk Advisories: SNYK-JS-MBT-16321404, SNYK-JS-CAPJSDBSERVICE-16321402, SNYK-JS-CAPJSSQLITE-16321405, SNYK-JS-CAPJSPOSTGRES-16321403


Lyrie.ai Cyber Research Division — Senior Analyst Desk

Lyrie Verdict

Lyrie's autonomous defense layer flags this class of exposure the moment it surfaces — no signature update required.