Supply Chain Alert: TeamPCP Compromises SAP npm Ecosystem via ‘mini Shai-Hulud’ Campaign

An OIDC trusted-publishing misconfiguration, a Bun-runtime stealer, and exfiltration to victim-owned GitHub repos — the new shape of npm supply-chain attacks

Executive Summary

On April 29, 2026, between 09:55 UTC and 12:14 UTC, the threat actor tracked as TeamPCP published trojanized versions of several official SAP-related npm packages — including mbt and three @cap-js modules — in a campaign researchers have dubbed “mini Shai-Hulud.” The compromised releases introduce a preinstall hook that downloads a platform-specific Bun runtime from GitHub Releases and executes a credential-stealing payload (execution.js) capable of harvesting developer credentials, GitHub and npm tokens, GitHub Actions secrets, and cloud secrets from AWS, Azure, GCP, and Kubernetes.

Unlike traditional dependency-confusion or typosquatting attacks, this campaign exploited a configuration gap in npm’s OIDC trusted publishing: the publisher configuration for @cap-js/sqlite trusted any workflow in cap-js/cds-dbs, not just the canonical release-please.yml on main. A branch push with id-token: write permission was sufficient to mint a short-lived npm token and publish poisoned releases without provenance. Exfiltrated data is AES-256-GCM encrypted and pushed to public GitHub repositories on the victim’s own account with the description “A Mini Shai-Hulud has Appeared.” Over 1,100 such repositories have been observed at the time of writing — and this campaign is one of the first observed to specifically target AI coding agent configurations as a persistence and propagation vector.

Confirmed Infections
1,100+
Public GitHub repos with the “Mini Shai-Hulud” exfil description string
Payload Size
11.6 MB
Stealer with self-propagation, GitHub Actions injection, and AI-agent persistence
Attack Window
~2h 19m
Window between first and last poisoned publish on April 29, 2026

Technical Analysis

Root Cause: OIDC Trusted Publishing — Trust Boundary Too Wide

In November 2025, the cds-dbs team migrated to npm OIDC trusted publishing, a modern alternative to long-lived npm tokens stored as GitHub secrets. Under this scheme, a GitHub Actions workflow exchanges its OIDC identity token for a short-lived npm publishing token at run time — eliminating one of the most common npm credential-leak vectors.

The security of this scheme depends entirely on the trust policy configured on the npm side: which GitHub workflow, on which branch, in which repo, is allowed to claim the publishing identity. SafeDep’s post-incident analysis identifies the critical misconfiguration in plain language:

“npm’s OIDC trusted publisher configuration for @cap-js/sqlite trusted any workflow in cap-js/cds-dbs, not just the canonical release-please.yml on main. A branch push could exchange an OIDC token on behalf of the package if the workflow had id-token: write permission and the environment: npm reference.” — SafeDep

The practical attack sequence followed from this gap. After compromising the GitHub account of maintainer RoshniNaveenaS, TeamPCP:

  1. Pushed a modified workflow to a non-main branch of cap-js/cds-dbs.
  2. Triggered the workflow, which had id-token: write permission and referenced environment: npm.
  3. Exchanged the OIDC token for a short-lived npm publishing token.
  4. Printed the token to the workflow log and used it to publish poisoned versions of the three @cap-js packages — without provenance.

For the mbt package, the attack appears to have leveraged a compromised static npm token belonging to the cloudmtabot automation account, obtained through an as-yet-undetermined channel. Both vectors converge on the same lesson: migrating to OIDC reduces credential-theft risk, but it does not eliminate publishing risk unless the trust policy is scoped to a single canonical workflow on a protected branch.

Execution Chain: From preinstall Hook to Bun-Backed Stealer

Once a developer or CI/CD runner installed one of the poisoned packages, the attack unfolded through a multi-stage execution chain that quickly escaped the boundaries of a typical npm install:

Mini Shai-Hulud Execution Chain
From npm install to credential exfiltration
1. Triggerpackage.json declares a preinstall script — new behavior not present in prior releases of these packages.
2. LoaderThe hook executes setup.mjs, which acts as a bootstrapper for the next stage.
3. Runtime fetchsetup.mjs downloads a platform-specific Bun ZIP archive from GitHub Releases, following HTTP redirects without destination validation.
4. Bun executionThe archive is extracted and the Bun binary is launched. On Windows, the launch uses powershell.exe -ExecutionPolicy Bypass to sidestep script restrictions.
5. StealerBun executes execution.js — the 11.6 MB credential-stealing and self-propagation framework.

The choice of Bun rather than the host’s existing Node.js installation is deliberate. Bun ships as a single statically-linked binary and provides a predictable, attacker-controlled JavaScript runtime regardless of what Node version, package manager, or transpiler the victim’s environment uses. The tradeoff — pulling tens of megabytes from GitHub Releases during npm install — is offset by execution consistency and the use of a domain (github.com) that is almost universally allowlisted in enterprise egress policies.

Credential Harvesting and Encryption

According to Aikido Security, the execution.js stealer enumerates and exfiltrates the following secret classes:

Local Developer Surface
  • Shell history, environment variables, dotfiles
  • npm and GitHub personal access tokens
  • SSH keys and config files
  • Cached cloud CLI credentials (~/.aws, ~/.config/gcloud, ~/.azure)
  • VS Code and AI coding-agent configuration files
CI/CD and Cloud Surface
  • GitHub Actions secrets and environment variables
  • AWS, Azure, GCP service-account credentials
  • Kubernetes service-account tokens and kubeconfigs
  • Container registry credentials
  • Workflow artifacts and build-time secrets

Harvested data is encrypted with AES-256-GCM before exfiltration. The choice of an AEAD cipher with integrity protection is consistent with an actor concerned about token validity surviving transit — GCM’s authentication tag guards against the corruption or tampering of stolen credentials, which can otherwise render bearer tokens useless on arrival.

Exfiltration via Victim-Owned GitHub Repos

The campaign’s most distinctive operational signature is the exfiltration channel. Rather than calling out to an attacker-controlled C2 endpoint, the stealer uses the victim’s own GitHub credentials to create public repositories on the victim’s own account, then pushes the encrypted secret bundles into those repos. Every such repo is created with the description string:

A Mini Shai-Hulud has Appeared.

This pattern provides three operational advantages for the attacker:

  • Egress trust. Traffic to github.com from a developer workstation or CI runner is rarely blocked or even logged at the firewall layer.
  • Attribution laundering. The exfiltrated data is stored in a repository owned by the victim — not an attacker-controlled endpoint that could be sinkholed or attributed.
  • Public indexing. Because the repos are public, the attacker can retrieve their contents from any IP at any time, with no inbound C2 channel to defend.

Self-Propagation and AI Agent Targeting

Beyond credential harvest, the 11.6 MB payload includes capabilities for autonomous lateral movement that distinguish this attack from earlier npm-borne stealers:

  • Workflow injection. Using the stolen GitHub and npm tokens, the malware injects a malicious GitHub Actions workflow into the victim’s other repositories to harvest their secrets and publish poisoned npm packages from those repos — a worm-style propagation pattern.
  • AI agent persistence. StepSecurity flagged this campaign as one of the first observed supply-chain attacks to target AI coding agent configuration files. Injected files are designed to trigger execution when opened by AI agents in VS Code — an emerging persistence vector that piggybacks on the trust relationship between developers and their AI assistants.

This last detail is the strategic story. As AI coding agents move from research curiosity to production tooling, their configuration files become a new high-value target: a single tainted configuration can re-trigger compromise every time the agent is invoked, regardless of whether the original poisoned npm package has been removed.


Affected Packages and Scope

Confirmed Compromised Packages — April 29, 2026
PackageMaintainer VectorRole in SAP Stack
mbtCompromised cloudmtabot static npm tokenMulti-Target Application Build Tool — primary SAP BTP build toolchain
@cap-js/sqliteOIDC trust policy abused via non-main branch workflowSQLite database driver for SAP Cloud Application Programming Model (CAP)
@cap-js/* (two additional modules)Same OIDC trust-policy gap; RoshniNaveenaS account compromiseCompanion @cap-js modules in the CAP ecosystem

The blast radius extends well beyond a literal count of poisoned versions. mbt is the canonical build tool for SAP’s Multi-Target Application format — the standard packaging mechanism for SAP Business Technology Platform deployments — and the @cap-js modules sit at the core of the CAP framework used by SAP and its customers to build cloud-native business applications. Any pipeline that ran npm install against the poisoned versions between 09:55 and 12:14 UTC on April 29, 2026 should be treated as compromised, with credentials rotated accordingly.


Indicators of Compromise (IOCs)

The most reliable detection for this campaign is the exfiltration-repository signature. Several supporting telemetry signals are also reliable in combination:

  • GitHub repo description (high fidelity): "A Mini Shai-Hulud has Appeared." — public repos with this exact description, created on or after 2026-04-29, on developer or service accounts.
  • npm preinstall: Newly-introduced preinstall script in package.json for mbt or @cap-js/* packages installed on or around April 29, 2026.
  • Filenames dropped on disk: setup.mjs and execution.js in the package install tree.
  • Bun binary download: Outbound HTTPS from a build agent or developer workstation to github.com/.../releases/.../bun-*.zip during npm install.
  • Windows process tree: node.exepowershell.exe -ExecutionPolicy Bypass spawned from an npm/yarn/pnpm install context.
  • Unexplained GitHub Actions workflow changes: New or modified workflows in repositories tied to compromised tokens, particularly those granting id-token: write.
Note on illustrative rules: The detection logic below is illustrative and synthesized from the publicly reported behavior of this campaign. Validate against your own telemetry before deploying it in production.
# Illustrative Sigma-style detection rule
title: TeamPCP Mini Shai-Hulud Exfiltration Repo Created
id: illustrative-mini-shai-hulud-2026-04
description: Detects victim-owned GitHub repos used as exfiltration sinks
logsource:
  product: github
  service: audit
detection:
  selection:
    action: repo.create
    repo.visibility: public
    repo.description|contains: "A Mini Shai-Hulud has Appeared."
  condition: selection
level: high
references:
  - https://thehackernews.com/2026/04/sap-npm-packages-compromised-by-mini.html
# Illustrative EDR rule — Windows preinstall → PowerShell bypass
title: npm preinstall spawns powershell with execution-policy bypass
detection:
  parent_process:
    image|endswith:
      - '\node.exe'
      - '\npm.cmd'
      - '\pnpm.cmd'
      - '\yarn.cmd'
  child_process:
    image|endswith: '\powershell.exe'
    command_line|contains: '-ExecutionPolicy Bypass'
  condition: parent_process and child_process
level: high

Mitigation & Remediation

  1. Update affected packages immediately. The cds-dbs team and the mbt maintainers have published clean versions that supersede the poisoned releases. Pin to the post-incident versions and verify integrity hashes.
  2. Treat any environment that ran the poisoned versions as compromised. Rotate every credential the install context had access to — GitHub tokens, npm tokens, Actions secrets, cloud credentials, kubeconfigs, and any SSH keys exposed on the host.
  3. Audit your GitHub org for the exfiltration signature. Query for repos with the description “A Mini Shai-Hulud has Appeared.” across every member account and service identity. Treat any match as a confirmed compromise, not a curiosity.
  4. Scope your npm OIDC trusted publisher configurations. Restrict each package’s trust policy to a specific repo, a specific workflow file, and the canonical release branch (main). Reject any policy that allows arbitrary workflows or branches.
  5. Disable npm install scripts in CI. Use npm ci --ignore-scripts in pipelines wherever feasible, and explicitly allowlist the packages that legitimately require lifecycle scripts.
  6. Block or alert on npm install processes that spawn PowerShell with -ExecutionPolicy Bypass. This pattern is rare in legitimate workflows and high-signal for this and similar campaigns.
  7. Audit AI coding agent configuration files for unexpected modifications. Treat agent configs as code — require review for changes, and monitor for files that execute on agent invocation.
  8. Pin and hash-verify dependencies. Use lockfiles with integrity hashes (npm’s integrity field, yarn’s checksums). For high-trust pipelines, mirror critical dependencies to an internal registry and gate updates through review.

Strategic Context: Why This Pattern Matters

The “mini Shai-Hulud” campaign is, on its surface, a single supply-chain incident affecting a handful of SAP-adjacent packages. The strategic story is more important than the incident itself. Three trends converge:

The TeamPCP Playbook

Trust the maintainer, attack the publishing pipeline

Modern supply-chain attacks no longer require malicious code review or social-engineered maintainers. They require finding a misconfigured OIDC trust policy, a leaked CI token, or an over-broad workflow permission — and turning the publishing pipeline itself into the delivery mechanism.

Defenders must shift their threat model accordingly: protect not just the code, but the path that code takes from commit to registry.

First, the attack succeeded not despite OIDC trusted publishing but through it — a reminder that adopting a more secure publishing primitive only helps if the trust policy is scoped tightly. Over-broad trust on a modern primitive can be worse than a narrow long-lived secret, because it provides an attacker with provenance-grade legitimacy.

Second, the use of victim-owned GitHub repos as the exfiltration sink converts the defender’s own trusted infrastructure into the attacker’s C2. Egress-based detections are blind to this pattern; only behavioral analysis at the endpoint or at the GitHub audit-log layer catches it.

Third, the targeting of AI coding agent configurations as a persistence vector is the leading edge of a new class of supply-chain attack. As AI agents are granted progressively more autonomy over a developer’s environment — reading repos, writing code, running commands — the configuration files that govern that autonomy become as security-sensitive as kernel modules.


Karma-X Perspective

Static signature-based defenses cannot keep pace with supply-chain attacks of this shape: the malicious payload is downloaded fresh from GitHub during install, the runtime is a legitimate JavaScript engine, and the exfiltration sink is the victim’s own GitHub account. There is no malicious IP to blocklist and no malicious hash to ban. What works is behavioral protection at machine speed — detecting and blocking the process behavior of an npm install that spawns PowerShell with bypass flags, fetches a runtime binary from GitHub Releases, enumerates dotfiles and CLI credential caches, and uses local credentials to create remote public repositories.

This is the class of attack that Karma-X is purpose-built to interrupt: high-velocity, novel, and supply-chain-borne, with no prior IOC. The endpoint is the only vantage point where the full behavioral chain is observable in time to stop it — and that is where modern defense must live.


Timeline

November 2025
OIDC migration. The cds-dbs team migrates to npm OIDC trusted publishing, eliminating long-lived secrets but configuring the trust policy to permit any workflow in the repo.
2026-04-29 09:55 UTC
First poisoned release. TeamPCP begins publishing trojanized versions of mbt and the @cap-js modules.
2026-04-29 12:14 UTC
Last poisoned release. Publishing window closes after roughly 2 hours and 19 minutes of malicious releases.
2026-04-30
Public disclosure. Aikido Security, SafeDep, Socket, StepSecurity, and Google-owned Wiz publish coordinated analyses; maintainers ship clean versions superseding the poisoned releases.
2026-04-30
Scope confirmation. Over 1,100 public repositories matching the “A Mini Shai-Hulud has Appeared” exfiltration description are documented — the visible floor of the infection count.

Sources & References

  1. The Hacker News. SAP-Related npm Packages Compromised in Credential-Stealing Mini Shai-Hulud Campaign. Link
  2. BleepingComputer. Official SAP npm packages compromised to steal credentials. Link
  3. BitNewsBot. Supply Chain Attack Hits SAP Npm Packages With Malware. Link
  4. Socket. Compromised SAP CAP npm packages download and execute unverified binaries. Link
  5. Hendry Adrian. Official SAP npm packages compromised to steal credentials. Link