cd /news/ai-safety/miasma-worm-infects-multiple-leoplat… · home topics ai-safety article
[ARTICLE · art-38800] src=safedep.io ↗ pub= topic=ai-safety verified=true sentiment=↓ negative

Miasma Worm Infects Multiple LeoPlatform npm Packages

A Miasma worm variant infected 20 npm packages under the LeoPlatform organization on June 24, 2026, after an attacker compromised a single maintainer's tokens. The malicious payload, a polymorphic credential stealer and self-propagating worm, was delivered via a binding.gyp file that bypasses lifecycle script scanners. Combined weekly downloads of the affected packages total approximately 13,600.

read10 min views1 publishedJun 25, 2026
Miasma Worm Infects Multiple LeoPlatform npm Packages
Image: Safedep (auto-discovered)

Table of Contents

A Miasma worm variant hit the LeoPlatform npm ecosystem on June 24, 2026. The attacker compromised a single maintainer’s npm and GitHub tokens and used them to publish infected versions of 20 packages in a 3-second burst. The same tokens pushed weaponized GitHub Actions workflows, disguised as Dependabot, to at least three repos. The payload matches the Miasma supply chain attack toolkit documented in our earlier source code analysis: a polymorphically packed Bun-based credential stealer and self-propagating worm that targets npm, PyPI, RubyGems, GitHub, AWS, Kubernetes, HashiCorp Vault, and AI coding tool configurations.

Paste or upload a lockfile, parsed locally against 20 packages.

TL;DR #

20 npm packages under the LeoPlatform / LeoInsights org received malicious updates at2026-06-24T23:04:55Z

  • Every infected package contains a binding.gyp

that triggers the payload duringnpm install

, bypassing lifecycle script scanners - The payload is identical across all 20 packages after decryption (same SHA256), packed with per-package ROT cipher values and AES-128-GCM keys

  • The compromised maintainer account ( czirker

) also pushed orphansnapshot-* branches to three GitHub repos, each carrying a 5.2 MB worm payload and a fake “Dependabot Updates” workflow - Combined weekly download count across the 20 packages is roughly 13,600

The 20 infected packages #

All 20 packages were published within the same 3-second window. The npm registry time

metadata confirms they share a single automated publish run:

Ecosystem Package Version
1 npm rstreams-shard-util 1.0.1
2 npm leo-logger 1.0.8
3 npm rstreams-metrics 2.0.2
4 npm leo-cdk-lib 0.0.2
5 npm leo-auth 4.0.6
6 npm leo-streams 2.0.1
7 npm serverless-convention 2.0.4
8 npm leo-cache 1.0.2
9 npm leo-connector-elasticsearch 2.0.6
10 npm leo-connector-mysql 3.0.3
11 npm leo-connector-redshift 3.0.6
12 npm leo-connector-mongo 3.0.8
13 npm leo-sdk 6.0.19
14 npm serverless-leo 3.0.14
15 npm leo-cli 3.0.3
16 npm leo-config 1.1.1
17 npm leo-cron 2.0.2
18 npm leo-aws 2.0.4
19 npm leo-connector-oracle 2.0.1
20 npm solo-nav 1.0.1
No matching rows

The highest-traffic targets are leo-logger

(3,140 weekly downloads), `leo-sdk`

(1,830), `leo-aws`

(1,730), `leo-config`

(1,709), and `leo-streams`

(1,497). Four packages under the same maintainers were not infected: `leo-connector-common`

, `leo-connector-entity-table`

, `leo-connector-postgres`

, and `leo-connector-sqlserver`

. All four have their npm latest

dist-tag pointing to a prerelease version (-rc or -beta

). The worm likely skips packages where the latest tag is not a stable release.

How the infection works #

Every infected package received the same three modifications compared to its previous clean version.

1. A new binding.gyp file. The file contains a single node-gyp target that uses command expansion to run

node index.js

during npm install

:The <!(...) syntax is a GYP command expansion that runs a shell command during project generation. npm automatically invokes node-gyp rebuild

when a binding.gyp

is present, regardless of whether the package.json

defines any install

or postinstall

script. This bypasses tools that only inspect lifecycle scripts.

2. A replaced index.js. The original module code is wiped and replaced with a single-line obfuscated payload of roughly 5.2 MB. The obfuscation has three layers:

Each package uses a different ROT value (5, 8, 19, or 23) and a different set of AES-128-GCM keys. After decryption, every package yields the same two blobs:

Blob Purpose Decrypted SHA256
_b Bun runtime bootstrapper (907 bytes) ceff7c51d70832...ea154108
_p Worm payload (781,580 bytes) 9f93d77d328338...9a6db015

The _b

blob downloads Bun 1.3.13 from GitHub releases, caches the binary in a temp directory, and exposes a global getBunPath()

function. The _p

blob (the worm) is written to /tmp/p<random>.js and executed via bun run

. The temp file is deleted after execution.

3. A new bun dependency. Every infected

package.json

adds "bun": "^1.3.13"

. This is the npm Bun installer package, likely included as a fallback path for environments where the bootstrapper’s

curl

download fails.## Root cause: one compromised maintainer

The npm account czirker

(Clint Zirker,

) is the only maintainer present on all 20 infected packages. Other maintainers like [email protected]leoinsights , jgrantr

, and elsmob

appear on subsets, but czirker

is the common denominator. The worm used this account’s npm token for the mass publish and its GitHub token for the repo-level attacks.

A registry metadata query confirms the maintainer list:

The jump from 1.0.0

(November 2024) to 1.0.1 (June 24, 2026) is the infected version. This pattern repeats across all 20 packages: a long-dormant legitimate package suddenly receives a new version with a 5 MB index.js

and a binding.gyp

.

GitHub repo poisoning #

The worm did not stop at npm. GitHub event logs for three LeoPlatform repositories show czirker

creating orphan branches named snapshot-<hex>

at 22:50 UTC, roughly 14 minutes before the npm publishes:

The commit on the snapshot-f121a878

branch of LeoPlatform/Nodejs

tells the story. It is an orphan commit (no parent) authored as czirker

, with the message “chore: update dependencies”. It adds two files:

The _index.js

is the same 5.2 MB worm payload. The workflow is a weaponized GitHub Actions pipeline:

Three things stand out. The workflow triggers on every push

to any branch. It requests id-token: write

, which grants access to a GitHub OIDC token that can be exchanged for npm publish credentials via npm’s trusted publishing. And it is named “Dependabot Updates” to blend in with legitimate dependency PRs.

A follow-up commit, this time impersonating dependabot[bot]

, replaced the OIDC parameters with a direct NPM_TOKEN: ${{ secrets.NPM_TOKEN }} reference, suggesting the worm tries multiple publish strategies. Both the actions/checkout

and oven-sh/setup-bun SHAs point to legitimate releases (a January 2026 checkout fix and Bun setup v2.2.0, respectively).

The master branch of LeoPlatform/Nodejs

is clean. The weaponized workflow lives only on the orphan snapshot branch, where it would execute if merged or if a CI configuration runs workflows from all branches.

The worm payload #

The inner code uses the standard javascript-obfuscator pattern: a _0x66ee

string lookup table with 2,588 entries, a _0x42e6

decoder function, and a secondary runtime-constructed decoder (fb12914b2

) called 519 times to decrypt environment variable names and API endpoints.

Static string analysis of the decrypted payload reveals the same capability set documented in our Miasma source code analysis: Credential theft across npm, GitHub (PATs, OIDC, JWTs), PyPI, RubyGems, Kubernetes service account tokens, HashiCorp Vault, AWS (IAM keys, STS, IMDS, Secrets Manager, SSM), 1Password, JFrog Artifactory, and SSH private keys.

Secret scanning via regex patterns for auth tokens, private keys, and .npmrc

credentials:

AI coding tool targeting, the Miasma family signature: the payload references claudeSettingsPath

, cursorRulesPath

, geminiSettingsPath

, and vscodeTasksPath

.

npm worm propagation with automated package enumeration (npmRepos

, maxPackages

), version bumping (newVersion ), and publish tracking (totalPackages

, published

, failed

, publishStepIndex

).

GitHub Actions workflow scanning using regex for npm publish

and yarn publish

in CI configs, with hasIdTokenWrite

checks for OIDC-based publishing.

For a complete breakdown of each module, see Inside the Miasma Software Supply Chain Attack Toolkit.

Indicators of compromise #

Type Indicator Context
1 File binding.gyp Install-time trigger, added to every infected package
2 File Pattern index.js (~5.2 MB single line) ROT-N + AES-128-GCM obfuscated worm payload replacing original
3 npm Dependency bun@^1.3.13 Added to all infected packages to bootstrap Bun runtime
4 SHA256 (Bun bootstrapper) ceff7c51d70832c3ec8dd2744b606a23b3c924ef664ae23439b9b742ea154108 Decrypted _b blob (identical across all 20 packages)
5 SHA256 (worm payload) 9f93d77d32833a515bc406c46da477142bb1ac2babeecb6aa42f98669a6db015 Decrypted _p blob (identical across all 20 packages)
6 SHA1 (leo-logger-1.0.8.tgz) 24a0d9e496ec07ca978fab602d5f5e0b39fa03a0 Infected tarball
7 SHA1 (serverless-convention-2.0.4.tgz) 5e75c14b8acd5752819ab7a10874ddd6389f5238 Infected tarball
8 SHA1 (leo-cache-1.0.2.tgz) e973173fb757d2dab9c6424b440dd9f7cbe4f14a Infected tarball
9 SHA1 (rstreams-shard-util-1.0.1.tgz) a8cb86b78ca56befe90dc466642cb04b98079909 Infected tarball
10 GitHub Branch Pattern snapshot-<8 hex chars> Orphan branches created by the worm on compromised repos
11 GitHub Commit Author dependabot[bot] Impersonated author on worm commits
12 GitHub File _index.js (~5.2 MB) Worm payload dropped into GitHub repos
13 GitHub Workflow Name Dependabot Updates Weaponized workflow disguised as Dependabot
14 GYP Command <!(node index.js > /dev/null 2>&1 && echo stub.c) node-gyp command expansion trigger in binding.gyp
15 Bun Download URL github.com/oven-sh/bun/releases/download/bun-v1.3.13/ Runtime downloaded by the Bun bootstrapper
16 Temp File Pattern /tmp/p<random>.js Worm payload written to disk before Bun execution
No matching rows

Quick detection check. Any npm package that added a binding.gyp

containing <!(node index.js

in a recent version bump, combined with a new "bun"

dependency and an index.js

that grew to several megabytes, should be treated as infected.

Infected packages (CSV) #

Ecosystem Package Version
1 npm rstreams-shard-util 1.0.1
2 npm leo-logger 1.0.8
3 npm rstreams-metrics 2.0.2
4 npm leo-cdk-lib 0.0.2
5 npm leo-auth 4.0.6
6 npm leo-streams 2.0.1
7 npm serverless-convention 2.0.4
8 npm leo-cache 1.0.2
9 npm leo-connector-elasticsearch 2.0.6
10 npm leo-connector-mysql 3.0.3
11 npm leo-connector-redshift 3.0.6
12 npm leo-connector-mongo 3.0.8
13 npm leo-sdk 6.0.19
14 npm serverless-leo 3.0.14
15 npm leo-cli 3.0.3
16 npm leo-config 1.1.1
17 npm leo-cron 2.0.2
18 npm leo-aws 2.0.4
19 npm leo-connector-oracle 2.0.1
20 npm solo-nav 1.0.1
No matching rows

Inside the Miasma Software Supply Chain Attack Toolkit, source code analysis of the Miasma wormMiasma Worm Targets AI Coding Agents via GitHub Repos, the GitHub repo persistence variantMini Shai-Hulud Hits @redhat-cloud-services, 32 packages compromised via OIDC trusted publishing

  • npm
  • oss
  • malware
- supply-chain
- shai-hulud
- ai-coding-agents
  • github

Author

SafeDep Team

safedep.io

Share

The Latest from SafeDep blogs #

Follow for the latest updates and insights on open source security & engineering

The wshu.net npm Campaign Delivers a Multi-Stage Infostealer One actor seeded 15 npm packages across 13 throwaway scopes in a single morning, each shipping a ~270KB obfuscated down behind a postinstall hook. The down pulls a Rust infostealer from...

@withgoogle/stitch-sdk: Scope Squat Harvests Developer Credentials A malicious npm package squats the @withgoogle scope to impersonate Google Stitch, silently harvesting credentials from Claude Code, git, GitHub CLI, SSH keys, npm, and Docker on install.

MYRA: A Full Linux RAT Distributed via npm The npm package apintergrationpost is a red team RAT called MYRA with native C rootkit, triple persistence, fileless execution, live screen streaming, and process masquerade. This analysis documents...

Five npm Packages That Hide a Windows Binary Dropper Five npm packages published in a 12-minute burst split a Windows binary dropper across a fake utility toolkit. The hides in a preinstall hook, decodes its C2 from a helper package, and fetches...

Ship Code. #

Not Malware. #

Start free with open source tools on your machine. Scale to a unified platform for your organization.

── more in #ai-safety 4 stories · sorted by recency
── more on @leoplatform 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/miasma-worm-infects-…] indexed:0 read:10min 2026-06-25 ·