Malicious Versions of 20 Leo Platform npm Packages Target CI/CD Secrets

Summary
Step Security reports 20 malicious Leo Platform npm package versions published in a three-second burst on June 24, 2026. It links their toolkit to Miasma and says it steals CI/CD and cloud credentials, exfiltrates via victims’ GitHub tokens, and can spread through npm.
Key points
- Step Security says 20 Leo Platform package versions were maliciously published within a three-second window on June 24, 2026, following unauthorized access to maintainer credentials.
- The company analyzed [email protected] and spot-checked [email protected]; it reports the packages share a toolkit and delivery mechanism with the Miasma campaign.
- The install hook uses a binding.gyp shell expansion to execute code during installation, with a three-layer obfuscation chain involving ROT-N, AES-128-GCM, and obfuscator[.]io.
- The payload targets GitHub Actions runner memory and sweeps credentials from cloud providers, package registries, Kubernetes, Vault, and password managers.
- Stolen credentials are encrypted and committed to GitHub repositories using the victim's token; a discovered npm token can enable propagation by publishing malicious package versions through bypass_2fa.
- The report also describes workflow-file modification and passwordless sudo changes on GitHub-hosted runners, and flags suspicious binding.gyp files without C++ sources or .node output.
Article Details
- Attack Vectors
- An unauthorized actor published malicious versions of 20 Leo Platform npm packages in a coordinated three-second burst after gaining access to maintainer credentials.
- A binding.gyp install hook used node-gyp shell expansion to execute commands during package installation without an entry in package.json's scripts block.
- The payload read Runner.Worker process memory on GitHub Actions runners to recover secrets masked in workflow logs and unavailable to child processes.
- The toolkit searched cloud credential sources, token files, package registries, password managers, and Kubernetes service-account tokens.
- Stolen credentials were encrypted and committed to GitHub repositories through the GitHub GraphQL API using the victim's GitHub token.
- When it found an npm token, the payload could publish malicious package versions to packages the victim could publish, using a bypass_2fa mechanism.
- The payload modified GitHub Actions workflow files to request id-token: write permission and add steps referencing attacker-controlled pinned action SHAs.
- On GitHub-hosted runners, the payload added a passwordless sudo rule.
- Defensive Notes
- Treat packages with a binding.gyp file but no C++ sources and no .node output as suspicious.
- Monitor CI/CD runners for the anomalous process chain node-gyp spawning curl, unzip, and bun, and for unauthorized reads of runner process memory.
- Use a configurable cooldown period for newly published npm versions to delay their availability to developer machines and CI/CD pipelines.
- Check repositories, pull requests, and enrolled developer machines for the affected package names and versions.
- The article reports that Harden-Runner can detect the described process chain and memory read, then terminate the workflow run.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| SHA1 | 1a5a1445fcd73133f22a0e7895993ac0a42b56da | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 1dcc0a39e1cd7293a9058cfc41e1afe8b397c943 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 24a0d9e496ec07ca978fab602d5f5e0b39fa03a0 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 47d73156df1c767bb168c4309fd17b92324d587d | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 5e75c14b8acd5752819ab7a10874ddd6389f5238 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 68a1cd589b2ce322f5f03fe7f85dc3f176a759d4 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 809ce3680adfdb8f0746189b68b6b5a6888a960f | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 888094a9b842cfe98e8e24c8f729be1fb6384563 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 92221eb202e9f2ac577e5c33658c8a05c6d67556 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | 9be49287057cd6a54ef4a70a8d541a7259efbd2d | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | a8cb86b78ca56befe90dc466642cb04b98079909 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | be3b1f7f1b50f5d53b164a72fb3a9845f4734325 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | be6bb1cf88c46e9e4a6f1a68ed001b77769d58de | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | d45ad3cffbcc7c4b354ebe9d71d002fa585379ec | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | d7224b6b1f5d2f9403f1cebc8f82518c20b4d0f7 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | e973173fb757d2dab9c6424b440dd9f7cbe4f14a | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | ed9a17d6567101fa4f9f552a4a52cfcca88fa662 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | ef8bf6dd92cbc29ef8d23f3f0fa786ed20a856b1 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | effa8576594fdd59907b5c5c07293ce28a9a3393 | SHA1 of the confirmed malicious [email protected] package. |
| SHA1 | f03a3e0dca9ef402352ce61cad59e5d850744960 | SHA1 of the confirmed malicious [email protected] package. |
MITRE ATT&CK
T1003.007 · Proc FilesystemThe payload reads /proc/{pid}/mem for the GitHub Actions Runner.Worker process to recover secrets.T1059.004 · Unix ShellThe binding.gyp hook uses node-gyp shell expansion to execute commands during package installation.T1059.007 · JavaScriptThe install hook runs index.js with Node.js, and the payload executes a temporary JavaScript file with Bun.T1195.002 · Compromise Software Supply ChainThe payload publishes malicious npm package versions using a victim's npm token and publish permissions.T1548.003 · Sudo and Sudo CachingOn GitHub-hosted runners, the payload writes a passwordless sudo rule for the runner.T1550.001 · Application Access TokenThe payload uses the victim's GitHub token to commit stolen credentials through the GitHub GraphQL API.T1552.001 · Credentials In FilesThe payload searches token-file locations, including HashiCorp Vault token files and Kubernetes service-account tokens.T1552.005 · Cloud Instance Metadata APIThe credential sweep queries cloud metadata services, including AWS IMDS and the GCP metadata service.T1555.005 · Password ManagersThe payload's credential sweep includes 1Password.T1567.001 · Exfiltration to Code RepositoryStolen credentials are encrypted and exfiltrated by committing them to GitHub repositories.
Products
GitHubless 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 exfiltratesGitHub Actionsthan 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 themnpmOn 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
