Update 1520 UTC, 30 April 2026: Two additional packages were trojanized today:
NPM Package: intercom-client@7.0.5
PyPI package lightning@2.6.2 and 2.6.3
Both packages appear to contain the same malicious functionality previously seen in the SAP operation. Analysis is ongoing.
Update 2140 UTC, 20 April 2026: Lightning and intercom-client payload analysis
Analysis of the malicious payloads shows an evolution in both exfiltration and credential harvesting techniques. In addition to earlier GitHub-based exfiltration, the malware now leverages dedicated infrastructure, primarily the domain zero.masscan.cloud, while also implementing a dynamic fallback mechanism.
The fallback retrieves configuration data from GitHub by searching for commits containing a specific keyword (“beautifulcastle”), which embeds a base64-encoded payload pointing to an exfiltration endpoint (currently resolving to 94.154.172[.]43/v1/telemetry. This approach allows attackers to update exfiltration infrastructure without publishing new malicious package versions.
The payload found in the intercom-client package further expands capabilities by actively scanning for secrets in Kubernetes environments and HashiCorp Vault. It queries Kubernetes service endpoints and Vault configurations, using extensive regex-based matching to extract credentials such as AWS keys, GitHub and npm tokens, database connection strings, private keys, and API secrets (e.g., Stripe, Slack, Twilio). This indicates a strong focus on cloud-native environments and CI/CD pipelines, significantly increasing the potential impact of the compromise through automated large-scale credential harvesting.
Update 1745 UTC, 29 April 2026: TeamPCP attribution confirmed and new functionality documented.
A new supply chain operation from TeamPCP calling itself “Mini Shai Hulud” compromised SAP-related npm packages by injecting malicious preinstall scripts that execute during dependency installation. The campaign leverages a multi-stage payload to harvest developer and CI/CD secrets across GitHub, npm, and major cloud providers, and exfiltrates the data via attacker-controlled GitHub repositories. It also contains code designed to propagate via compromised tokens. TeamPCP is very likely responsible for this campaign, based on a shared RSA public key and overlaps in encoding routines and region guardrails.
What happened?
Malicious versions of legitimate SAP ecosystem packages (e.g., `@cap-js/sqlite`, `@cap-js/postgres`) were created by modifying them to include a `preinstall` script that executes `setup.mjs` automatically during `npm install`. This script downloads the Bun runtime and executes an obfuscated payload (`execution.js`), enabling attacker-controlled code execution prior to package installation completion.
When executed, the second-stage payload is a credential stealer and propagation framework designed to target both developer environments and CI/CD pipelines. It collects sensitive data including GitHub tokens, npm credentials, cloud secrets (AWS, Azure, GCP), Kubernetes tokens, and GitHub Actions secrets—leveraging advanced techniques such as extracting secrets from runner memory. Exfiltration occurs via public GitHub repositories, where it posts encrypted payloads. Additionally, the malware includes propagation logic to infect additional repositories and package distributions.
During its initial setup, the malware performs a system check to determine if the compromised machine is configured for the Russian language. It does this by inspecting both the system's date/time locale settings and its environment language variables. If any of these values begin with 'ru', the payload abruptly terminates itself, ensuring no data is exfiltrated from Russian-speaking systems.
While we estimate this campaign is currently active, the volume of compromised users and attacker-created exfiltration repositories appears significantly lower than that of Shai-Hulud or Shai-Hulud 2.0.
Notable Updates
This operation broadly follows the same methods used in previous TeamPCP operations, but contains a number of notable evolutions.
Github Exfiltration
In the Bitwarden operation, the malware would attempt to exfiltrate the encrypted blob of secrets to GitHub only if the primary exfiltration mechanism to a C&C domain failed. In this operation, exfiltration to GitHub is the primary and only way to exfiltrate secrets. The mechanisms are substantially similar, using the same naming scheme (word1-word2-number) and the same repo description “"Checkmarx Configuration Storage" The biggest change is that the SAP operation uses the GraphQL API, rather than the REST API, which was used in the Bitwarden operation.
Fallback to GitHub Poisoning
If the credential collection is not able to identify a gh[op]_ (PAT/OAuth) token and GITHUB_REPOSITORY is set it will attempt to poison that GitHub repository. It does this only if ghs_ or ghs_old tokens are present (and no GitHub PAT tokens are). The below files are placed in the repo, in an attempt to infect users who open the repo in Claude Code or VSCode:
| Path | Content | Purpose | Hashes |
|---|---|---|---|
| .claude/execution.js | Self-copy of the running payload via Bun.main | Payload for Claude Code users | Identical to the initial execution.js |
| .claude/setup.mjs | The dropper | Dropper that downloads Bun and executes the payload | Identical to the initial setup.mjs |
| .claude/settings.json | Claude Code hooks configuration | Claude Code SessionStart hook — runs node .vscode/setup.mjs on every session | SHA256: 14eb4ce01dd4307759887ff819359b70d7d9ff709ecde039a5abc1aac325b128 SHA1: ff7ed7a0fa1c43eed01809d076feedbaed464fc7 MD5: 00ca0c04d247ef09f2b2acc452029345 |
| .vscode/tasks.json | VS Code task configuration | VS Code task "Environment Setup" — runs node .claude/setup.mjs on folder open (runOn: folderOpen) | SHA256: 927387d0cfac1118df4b383decc2ea6ba49c9d2f98b47098bcbcba1efc026e1f SHA1: 7b0278216ac31ec18eca9eb8bc1c1261a1b26f6c MD5: dbb9b09957113463bbeb420c2c4108b5 |
| .vscode/setup.mjs | Same dropper as .claude/setup.mjs | Dropper for VS Code execution path | Identical to the initial setup.mjs |
Browser Credential Theft
The SAP operation adds the ability to steal credentials from multiple browsers (Chrome, Safari, Edge, Brave, Chromium) and exfiltrate any passwords found there. This feature was not present in any of the previous operations.
Exfiltration Fallback Mechanism
Consistent with previous Shai-Hulud attacks, this new variant utilizes a fallback mechanism to exfiltrate secrets from environments lacking local GitHub (GH) tokens or credentials. If local credential harvesting fails, the malware actively searches GitHub for commits beginning with a specific signature phrase: "OhNoWhatsGoingOnWithGitHub".
This phrase is the default commit message the malware uses when exfiltrating data. Appended to this phrase is a double-base64 encoded GitHub token:
"message": "OhNoWhatsGoingOnWithGitHub:WjJodlh[Redacted]" Once located, the malware extracts and validates this token to facilitate further data exfiltration. Consequently, even if your organization has not created any new repositories, your secrets may still be compromised and routed to an entirely unrelated, attacker-controlled repository.
Attribution
Wiz assesses with high confidence that this is the work of the same TeamPCP operators that have previously compromised multiple libraries. This assessment is due to a shared RSA public key used to encrypt the exfiltrated secrets. This means that the same private key would decrypt the payloads, limiting the accessibility of the exfiltrated data to TeamPCP.
Additional commonalities:
The malware has an early check for the system language and if it is found to be “ru” the malware exits and does not exfiltrate any secrets. This was previously present in the Checkmarx and Bitwarden compromises.
The package uses the same npm install hook to start execution that was used in the Bitwarden CLI compromise.
GitHub based exfiltration to Dune themed repos was the fallback C2 method for the Bitwarden CLI operation, but is now the primary option.
While this operation contains references to the Shai-Hulud operations from the fall of 2025, we cannot definitively link them or say they are a separate actor.
Affected Packages
npm packages:
@cap-js/sqlite – v2.2.2
@cap-js/postgres – v2.2.2
@cap-js/db-service – v2.10.1
mbt – v1.2.48
Indicators of compromise
@cap-js/postgres 2.2.2
| File | Hash |
|---|---|
| Tarball (3,409,213 bytes) | SHA256: 1d9e4ece8e13c8eaf94cb858470d1bd8f81bb58f62583552303774fa1579edee |
| Tarball (3,409,213 bytes) | SHA1: e80824a19f48d778a746571bb15279b5679fd61c |
| Tarball (3,409,213 bytes) | MD5: e32eaf0c3cde9616831a1e92d42b0058 |
| execution.js (11,723,748 bytes) | SHA256: eb6eb4154b03ec73218727dc643d26f4e14dfda2438112926bb5daf37ae8bcdb |
| execution.js (11,723,748 bytes) | SHA1: ca4a5bb85778ffcd2153ace88fe2d882c8ceeb23 |
| execution.js (11,723,748 bytes) | MD5: b523a69b27064d1715d1f0aaffcfae63 |
@cap-js/db-service 2.10.1
| File | Hash |
|---|---|
| Tarball (3,490,641 bytes) | SHA256: 258257560fe2f1c2cc3924eae40718c829085b52ae3436b4e46d2565f6996271 |
| Tarball (3,490,641 bytes) | SHA1: 4b04304f6d51392e3f43856c94ca95800518a694 |
| Tarball (3,490,641 bytes) | MD5: d468f16eafccbc54a994f3d675ace8ae |
| execution.js | Identical to @cap-js/postgres 2.2.2 |
@cap-js/sqlite 2.2.2
| File | Hash |
|---|---|
| Tarball (3,395,651 bytes) | SHA256: a1da198bb4e883d077a0e13351bf2c3acdea10497152292e873d79d4f7420211 |
| Tarball (3,395,651 bytes) | SHA1: 7b6a28e92149637e5d7c7f4a2d3e54acd507c929 |
| Tarball (3,395,651 bytes) | MD5: 8cd683f78735c9bfc32600c73d3d9abe |
| execution.js (11,729,871 bytes) | SHA256: 6f933d00b7d05678eb43c90963a80b8947c4ae6830182f89df31da9f568fea95 |
| execution.js (11,729,871 bytes) | SHA1: bc95cc5dda788295aa0c9456791520599ef99526 |
| execution.js (11,729,871 bytes) | MD5: 6fb87d243b011b5445f379f80e1a6b4d |
mbt 1.2.48
| File | Hash |
|---|---|
| Tarball (3,373,788 bytes) | SHA256: 86282ebcd3bebf50f087f2c6b00c62caa667cdcb53558033d85acd39e3d88b41 |
| Tarball (3,373,788 bytes) | SHA1: 0af7415d65753f6aede8c9c0f39be478666b9c12 |
| Tarball (3,373,788 bytes) | MD5: 04d8a99447b16f6839fff3b978f88d7e |
| execution.js (11,678,349 bytes) | SHA256: 80a3d2877813968ef847ae73b5eeeb70b9435254e74d7f07d8cf4057f0a710ac |
| execution.js (11,678,349 bytes) | SHA1: 6bc859aaee1f8885eec2a3016226e877e5adba08 |
| execution.js (11,678,349 bytes) | MD5: 45dc9c02f82b4370ca92785282d43a86 |
Shared Dropper (all 4 packages)
| File | Hash |
|---|---|
| setup.mjs (4,549 bytes) | SHA256: 4066781fa830224c8bbcc3aa005a396657f9c8f9016f9a64ad44a9d7f5f45e34 |
| setup.mjs (4,549 bytes) | SHA1: 307d0fa7407d40e67d14e9d5a4c61ac5b4f20431 |
| setup.mjs (4,549 bytes) | MD5: 35baf8316645372eea40b91d48acb067 |
What steps should security teams take?
Immediately identify exposure: Search environments, lockfiles, artifact stores, and CI logs for affected package versions and malicious files (setup.mjs, execution.js).
Rotate all credentials: If exposure is suspected, rotate GitHub tokens, npm tokens, cloud credentials, Kubernetes tokens, and CI/CD secrets, this malware targets all of them.
Audit GitHub activity: Look for suspicious commits, newly created repositories, or indicators such as the propagation keyword and unusual commit authors.