# SAP CAP & Cloud MTA npm Packages Compromised — Mini Shai-Hulud (TeamPCP) Bun-Based Credential Stealer

> On 2026-04-29, four official SAP-related npm packages (mbt, @cap-js/db-service, @cap-js/postgres, @cap-js/sqlite) — with ~570K combined weekly downloads — were trojanized with a malicious preinstall hook (setup.mjs) that downloads the Bun JavaScript runtime to execute an obfuscated credential harvester (execution.js). The malware exfiltrates SSH keys, cloud tokens (AWS/Azure/GCP), npm/GitHub tokens, Kubernetes/Docker configs, and CI runner secrets as RSA-OAEP-4096 ciphertext to attacker-controlled GitHub repositories tagged 'A Mini Shai-Hulud has Appeared'. Researchers attribute the campaign with medium confidence to TeamPCP based on a shared __decodeScrambled cipher and Russian-locale kill switches that match prior Trivy, LiteLLM, Checkmarx, and Bitwarden npm compromises.

- **Published:** 2026-04-30T12:00:00Z
- **Last reviewed:** 2026-04-30T12:00:00Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-0439
- **ID:** TL-2026-0439
- **Severity:** CRITICAL
- **Category:** SUPPLY_CHAIN
- **Status:** MONITORING
- **Actor:** TeamPCP
- **Detections:** 9 · **IOCs:** 22 (full data via the Threadlinqs MCP server — Purple tier)

## Description

On 2026-04-29 Socket Threat Research disclosed a coordinated supply-chain compromise of four SAP-affiliated npm packages: mbt 1.2.48 (Cloud MTA Build Tool, ~52K weekly downloads), @cap-js/db-service 2.10.1 (~260K), @cap-js/postgres 2.2.2 (~10K), and @cap-js/sqlite 2.2.2 (~250K). All four versions were published with an identical malicious package.json preinstall hook that runs node setup.mjs before the legitimate package code is unpacked, ensuring credential collection executes the moment a developer or CI runner runs npm install — even with --ignore-scripts=false defaults.

setup.mjs detects the host architecture (linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64), downloads the matching official Bun JavaScript runtime release from GitHub (github.com/oven-sh/bun/releases), unpacks it to a hidden directory under the user's home, and uses Bun to execute execution.js. The choice of Bun is operationally novel: it bypasses Node-level npm security tooling, provides single-binary execution that defeats some EDR JS-content inspection, and enables fast TypeScript-style execution of the obfuscated payload without a node_modules tree of its own. execution.js itself is heavily obfuscated using a __decodeScrambled cipher previously observed in TeamPCP-linked Trivy, LiteLLM, Checkmarx, and Bitwarden compromises.

Once decoded, the stealer enumerates the filesystem for ~/.ssh/* (id_rsa, id_ed25519, known_hosts, config), ~/.aws/credentials and config, ~/.azure/, ~/.config/gcloud/, ~/.docker/config.json, ~/.kube/config, ~/.npmrc, ~/.gitconfig, ~/.gnupg/, environment files (.env, .env.local), Helm/Terraform state, GitHub Actions runner working directories, and CI variables exposed via GITHUB_TOKEN, NPM_TOKEN, AWS_*, AZURE_*, GCP_* environment variables. It additionally queries the cloud Instance Metadata Service endpoints 169.254.169.254 (AWS IMDSv1/v2, Azure IMDS), 169.254.170.2 (AWS ECS task metadata v2), 127.0.0.1:40342 (Azure Instance Metadata legacy), and metadata.google.internal (GCP) to harvest IAM role temporary credentials.

Collected secrets are concatenated, encrypted with RSA-OAEP-4096 using a hard-coded attacker public key, and base64-encoded. The stealer then authenticates to GitHub using the victim's own discovered token and creates a public repository whose name follows the pattern <word>-<word>-<3 digits> with description 'A Mini Shai-Hulud has Appeared'. The encrypted blob is committed as a file with the message 'chore: update dependencies'. Operators retrieve victims by issuing a GitHub code search for the dead-drop query OhNoWhatsGoingOnWithGitHub, an embedded marker string. Before any of this runs, an execution-guardrail check inspects the system locale; if it contains a Russian (ru-*) language tag, execution exits cleanly — a signature of the broader campaign cluster.

The @cap-js/* package compromise vector was account takeover of legitimate SAP cap-js maintainer RoshniNaveenaS: the attacker pushed a modified GitHub Actions workflow on a non-main branch that exfiltrated the cap-js repository's npm OIDC token, then used that token to publish the malicious versions without provenance attestations. The mbt 1.2.48 compromise is suspected to involve the static npm publish token of the cloudmtabot SAP service account; the exact takeover channel is undetermined and under SAP investigation. SAP and the cap-js maintainers unpublished the malicious versions within hours, but anyone whose CI ran npm install or npm ci against an unpinned range during the exposure window — and whose lockfile resolved the malicious version — must assume cloud and source-control credentials are compromised, rotate every secret reachable from the affected runner, audit GitHub for repositories matching the naming and description signature created from their accounts, and remove any such repos.

## MITRE ATT&CK

- T1586 Compromise Accounts
- T1585.001 Establish Accounts: Social Media Accounts
- T1587.001 Develop Capabilities: Malware
- T1588.002 Obtain Capabilities: Tool
- T1195.002 Supply Chain Compromise: Compromise Software Supply Chain
- T1199 Trusted Relationship
- T1059.007 Command and Scripting Interpreter: JavaScript
- T1204.002 User Execution: Malicious File
- T1546 Event Triggered Execution
- T1027 Obfuscated Files or Information
- T1140 Deobfuscate/Decode Files or Information
- T1480 Execution Guardrails
- T1218 System Binary Proxy Execution
- T1036 Masquerading
- T1552.001 Unsecured Credentials: Credentials In Files
- T1552.004 Unsecured Credentials: Private Keys
- T1552.005 Unsecured Credentials: Cloud Instance Metadata API
- T1528 Steal Application Access Token
- T1083 File and Directory Discovery
- T1082 System Information Discovery
- T1526 Cloud Service Discovery
- T1005 Data from Local System
- T1560 Archive Collected Data
- T1102.002 Web Service: Bidirectional Communication
- T1573.002 Encrypted Channel: Asymmetric Cryptography
- T1105 Ingress Tool Transfer
- T1567.001 Exfiltration Over Web Service: Exfiltration to Code Repository

## Sources

- [TeamPCP-Linked Supply Chain Attack Hits SAP CAP and Cloud MTA npm Packages](https://socket.dev/blog/sap-cap-npm-packages-supply-chain-attack)
- [Official SAP npm packages compromised to steal credentials](https://www.bleepingcomputer.com/news/security/official-sap-npm-packages-compromised-to-steal-credentials/)
- [SAP-Related npm Packages Compromised in Credential-Stealing Supply Chain Attack](https://thehackernews.com/2026/04/sap-npm-packages-compromised-by-mini.html)
- [Mini Shai-Hulud Targets SAP npm Packages With a Bun-Based Secret Stealer](https://www.aikido.dev/blog/mini-shai-hulud-has-appeared)
- [Supply Chain Campaign Targets SAP npm Packages with Credential-Stealing Malware](https://www.wiz.io/blog/mini-shai-hulud-supply-chain-sap-npm)
- [Bun-Based Stealer Hits SAP CAP npm Packages](https://snyk.io/blog/bun-based-stealer-hits-sap-cap-js-mbt-npm-packages/)
- [MITRE ATT&CK T1195.002 Compromise Software Supply Chain](https://attack.mitre.org/techniques/T1195/002/)
- [MITRE ATT&CK T1567.001 Exfiltration to Code Repository](https://attack.mitre.org/techniques/T1567/001/)
- [MITRE ATT&CK T1552.005 Cloud Instance Metadata API](https://attack.mitre.org/techniques/T1552/005/)
- [Bun JavaScript Runtime — Official Releases (abused for malware execution)](https://github.com/oven-sh/bun/releases)

## Full data

Detection queries (Splunk SPL / Microsoft KQL / Sigma) and IOC values require the Threadlinqs MCP server (Purple tier): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-0439
