



























On June 24, 2026, an attacker published malicious versions of 20 npm packages belonging to the Leo Platform ecosystem in a coordinated burst spanning less than three seconds. All 20 packages carry an identical CI/CD attack toolkit that steals secrets from GitHub Actions runners, cloud credential stores, package registries, and password managers, then exfiltrates them via the victim's own GitHub token. Together these packages receive approximately 13,600 downloads per week.
We analyzed leo-logger@1.0.8 in full and spot-checked leo-sdk@6.0.19 to confirm the campaign scope. The attack uses the same toolkit and delivery mechanism we documented in our earlier post on the Miasma campaign: a "Phantom Gyp" binding.gyp install hook, a three-layer obfuscation chain (ROT-N cipher, AES-128-GCM, obfuscator.io), and Bun runtime evasion. For a full technical breakdown of the attack chain, see that post. This report focuses on the Leo Platform campaign specifics: the 20 affected packages, the coordinated publish, and remediation steps.
All 20 packages were published within a 3-second window at 2026-06-24T23:04:55Z, confirming a single automated operation against the Leo Platform maintainer accounts. The payload is structurally identical to the Miasma campaign published June 3, 2026, sharing the same binding.gyp hook syntax, the same three-layer obfuscation chain, and the same Bun v1.3.13 download URL. This seems to be the same threat actor targeting a new ecosystem, 21 days after Miasma.
The following 20 packages are confirmed malicious at the listed versions. All were published simultaneously by an unauthorized actor who gained access to the Leo Platform maintainer credentials.
| Package | Malicious Version |
|---|---|
leo-logger |
1.0.8 |
leo-sdk |
6.0.19 |
leo-aws |
2.0.4 |
leo-config |
1.1.1 |
leo-streams |
2.0.1 |
serverless-leo |
3.0.14 |
leo-connector-mongo |
3.0.8 |
serverless-convention |
2.0.4 |
rstreams-metrics |
2.0.2 |
leo-connector-elasticsearch |
2.0.6 |
leo-auth |
4.0.6 |
leo-cache |
1.0.2 |
leo-cli |
3.0.3 |
leo-cron |
2.0.2 |
leo-connector-redshift |
3.0.6 |
leo-connector-oracle |
2.0.1 |
rstreams-shard-util |
1.0.1 |
leo-connector-mysql |
3.0.3 |
leo-cdk-lib |
0.0.2 |
solo-nav |
1.0.1 |
On June 3, 2026 we published a detailed technical analysis of the Miasma campaign, which compromised 57 npm packages across 286+ versions using the same toolkit. The Leo Platform attack is structurally identical:
| Technique | Miasma (June 3) | Leo Platform (June 24) |
|---|---|---|
| Install hook | binding.gyp "Phantom Gyp" with <!(node index.js > /dev/null 2>&1 && echo stub.c)> |
Byte-for-byte identical |
| Obfuscation chain | ROT-N + AES-128-GCM + obfuscator.io (3 layers) | Same 3 layers |
| Bun version | v1.3.13 from GitHub Releases | Identical |
| Bun downloader blob | 907 bytes | Identical |
Runner.Worker /proc/{pid}/mem |
Yes | Yes |
| GitHub dead-drop exfil | Yes | Yes |
| npm supply chain worm | Yes, via bypass_2fa |
Yes, via bypass_2fa |
| Scale | 57 packages, 286+ versions, under 2 hours | 20 packages, 3-second burst |
The Leo Platform operation is more targeted and quieter than Miasma. It focuses on a single maintained ecosystem rather than carpet-bombing across maintainer accounts, and the publish window (3 seconds vs. under 2 hours) suggests the same automated payload factory operating with improved tooling. The binding.gyp hook syntax, the Bun download URL, and the three-layer obfuscation structure are fingerprints that tie both operations to the same actor.
The "Phantom Gyp" technique uses the node-gyp <!(...)> shell expansion inside the sources array to execute arbitrary commands at install time without declaring any entry in the scripts block of package.json. Any package that ships a binding.gyp file but has no C++ sources and no .node binary output should be treated as suspicious. For a full technical walkthrough of the obfuscation chain and payload capabilities, see our Miasma analysis.
The payload capabilities are documented in detail in the Miasma post. In summary, the toolkit does the following on every install:
Runner.Worker process via /proc/{pid}/cmdline, then reads /proc/{pid}/mem directly to recover secrets that are masked in workflow logs and invisible to child processes.bypass_2fa API mechanism, without triggering two-factor authentication.id-token: write permission and add steps referencing attacker-controlled pinned action SHAs.runner ALL=(ALL) NOPASSWD:ALL to grant passwordless sudo access.| Type | Value | Significance |
|---|---|---|
| Publish timestamp | 2026-06-24T23:04:55Z (all 20 packages within 3 seconds) |
Any Leo Platform package published in this window is compromised |
| Structural fingerprint | Char-code array of length 1,566,023 in index.js |
Unique to this payload factory; identifies any package from this campaign |
| binding.gyp hook | <!(node index.js > /dev/null 2>&1 && echo stub.c)> |
Phantom Gyp install-time execution; identical to Miasma campaign |
| Bun download | github.com/oven-sh/bun/releases/download/bun-v1.3.13/ |
Outbound connection during npm install; strong behavioral signal |
| Temp file execution | /tmp/p*.js executed by bun |
Payload drop location; definitive behavioral indicator |
| Memory access | /proc/{pid}/mem where target is Runner.Worker |
Runner secret extraction; definitively malicious in any CI/CD context |
| Worm capability | bypass_2fa |
npm 2FA bypass for supply chain propagation |
| Privilege escalation | runner ALL=(ALL) NOPASSWD:ALL |
Sudo escalation on GitHub-hosted runners |
| AES key (leo-logger Blob 1) | ad9f0ecdbf6075f8cc4ca8bdd62bd27c | Per-package unique; fingerprints leo-logger@1.0.8 specifically |
| AES key (leo-logger Blob 2) | 54089e0f368fa9a7e2050de9b0db121a | Per-package unique; fingerprints leo-logger@1.0.8 specifically |
| SHA1 (leo-logger@1.0.8) | 24a0d9e496ec07ca978fab602d5f5e0b39fa03a0 | |
| SHA1 (leo-sdk@6.0.19) | d45ad3cffbcc7c4b354ebe9d71d002fa585379ec | |
| SHA1 (leo-aws@2.0.4) | 1dcc0a39e1cd7293a9058cfc41e1afe8b397c943 | |
| SHA1 (leo-config@1.1.1) | ed9a17d6567101fa4f9f552a4a52cfcca88fa662 | |
| SHA1 (leo-streams@2.0.1) | effa8576594fdd59907b5c5c07293ce28a9a3393 | |
| SHA1 (serverless-leo@3.0.14) | 47d73156df1c767bb168c4309fd17b92324d587d | |
| SHA1 (serverless-convention@2.0.4) | 5e75c14b8acd5752819ab7a10874ddd6389f5238 | |
| SHA1 (leo-auth@4.0.6) | 809ce3680adfdb8f0746189b68b6b5a6888a960f | |
| SHA1 (leo-connector-mongo@3.0.8) | 68a1cd589b2ce322f5f03fe7f85dc3f176a759d4 | |
| SHA1 (leo-connector-elasticsearch@2.0.6) | be3b1f7f1b50f5d53b164a72fb3a9845f4734325 | |
| SHA1 (leo-connector-mysql@3.0.3) | f03a3e0dca9ef402352ce61cad59e5d850744960 | |
| SHA1 (leo-connector-redshift@3.0.6) | 888094a9b842cfe98e8e24c8f729be1fb6384563 | |
| SHA1 (leo-connector-oracle@2.0.1) | d7224b6b1f5d2f9403f1cebc8f82518c20b4d0f7 | |
| SHA1 (leo-cache@1.0.2) | e973173fb757d2dab9c6424b440dd9f7cbe4f14a | |
| SHA1 (leo-cli@3.0.3) | 92221eb202e9f2ac577e5c33658c8a05c6d67556 | |
| SHA1 (leo-cron@2.0.2) | be6bb1cf88c46e9e4a6f1a68ed001b77769d58de | |
| SHA1 (rstreams-metrics@2.0.2) | 1a5a1445fcd73133f22a0e7895993ac0a42b56da | |
| SHA1 (rstreams-shard-util@1.0.1) | a8cb86b78ca56befe90dc466642cb04b98079909 | |
| SHA1 (leo-cdk-lib@0.0.2) | ef8bf6dd92cbc29ef8d23f3f0fa786ed20a856b1 | |
| SHA1 (solo-nav@1.0.1) | 9be49287057cd6a54ef4a70a8d541a7259efbd2d |
StepSecurity has published a threat intel alert in the Threat Center with all relevant links to check if your organization is affected. The alert includes the full attack summary, technical analysis of the Phantom Gyp technique, IOCs, all affected packages and malicious versions, and remediation steps, so teams have everything needed to triage and respond immediately. Threat Center alerts are delivered directly into existing SIEM workflows for real-time visibility.

Harden-Runner is a purpose-built security agent for CI/CD runners. It monitors all network events, process executions, file access, and outbound network connections at the step level in GitHub Actions, providing full runtime visibility into what happens during every workflow step, including npm install.
Harden-Runner detects the anomalous process chain (node-gyp spawning curl, unzip, and bun) and the unauthorized memory read, immediately initiating lockdown mode. The workflow run is terminated, preventing any secrets from being extracted.
Link to the run : https://app.stepsecurity.io/github/actions-security-demo/test-comp/actions/runs/28155317636

StepSecurity Secure Registry provides each enterprise customer with a dedicated, policy-enforced npm registry that sits between your existing package manager (such as JFrog Artifactory) and the public npm registry. Instead of fetching packages directly from registry.npmjs.org, your infrastructure routes requests through your StepSecurity registry, which applies configurable security policies before serving any package.
The primary defense here is the cooldown period. Newly published package versions are held for a configurable window before being served to any developer machine or CI/CD pipeline. When the compromised Miasma packages were published to npm, including @vapi-ai/server-sdk, ai-sdk-ollama, and dozens of packages in the jagreehal ecosystem, Secure Registry customers were never exposed.

StepSecurity Dev Machine Guard gives security teams real-time visibility into npm packages installed across every enrolled developer device. When a malicious package is identified, teams can immediately search by package name and version to discover all impacted machines.

Newly published npm packages are temporarily blocked during a configurable cooldown window. When a PR introduces or updates to a recently published version, the check automatically fails. Since most malicious packages are identified within hours, this creates a crucial safety buffer. In this case, 57 packages across 286+ malicious versions were published in a rolling campaign lasting under two hours on June 3, so any PR updating to an affected version during the cooldown period would have been blocked automatically.

StepSecurity maintains a real-time database of known malicious and high-risk npm packages, updated continuously, often before official CVEs are filed. If a PR attempts to introduce a compromised package, the check fails and the merge is blocked. All compromised versions from this Miasma campaign, including @vapi-ai/server-sdk, ai-sdk-ollama, and the full jagreehal package family, were added to this database within minutes of detection.

Search across all PRs in all repositories across your organization to find where a specific package was introduced. When a compromised package is discovered, instantly understand the blast radius: which repos, which PRs, and which teams are affected. This works across pull requests, default branches, and dev machines.

此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。