Safeguard
Supply Chain Security•

LeoPlatform npm worm and a hijacked release action, 24 June 2026

A maintainer account takeover put 20 packages in the LeoPlatform and RStreams families on a Miasma worm that runs through binding.gyp, while a popular release action had its tags redirected.

Safeguard Security Team
4 min read

On 24 June 2026, attackers published malicious releases of 20 npm packages in the LeoPlatform and RStreams ecosystems after taking over a maintainer's npm account. Socket, StepSecurity, JFrog and SafeDep published analyses, according to a Hackmag summary of the campaign. The same day, StepSecurity linked it to a compromise of the codfish/semantic-release-action GitHub Action.

What's affected

  • npm packages in the LeoPlatform and RStreams families, including leo-auth, leo-aws, leo-cli, leo-sdk, leo-streams, serverless-leo and rstreams-metrics. The summary does not list versions.
  • The npm account involved is named czirker and is tied to the LeoPlatform maintainer. The attackers likely used leaked credentials to obtain an npm token, and published all 20 releases within seconds.
  • The GitHub Action codfish/semantic-release-action. On 24 June attackers force-pushed a malicious commit and redirected several version tags to it, per StepSecurity.
  • The Verana blockchain project's Go module. Its payload sat in repository config files and ran when a VS Code task executed node .claude/setup.mjs on opening the project. Downloading or building the module did not trigger it.

The npm releases differ from earlier Miasma waves: they run code during install through binding.gyp instead of package.json lifecycle hooks. The loader fetches the Bun runtime if needed, then starts the stealer. It stays idle on a Russian locale and goes after cloud credentials, GitHub and npm tokens, Kubernetes secrets, Vault and 1Password data, and IDE and AI assistant configuration.

How to check if you're exposed

grep -rnE "leo-(auth|aws|cli|sdk|streams)|serverless-leo|rstreams" package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null
grep -rn "codfish/semantic-release-action" .github/workflows
find node_modules -name binding.gyp -not -path "*/node-gyp/*" 2>/dev/null | head -50

Check any workflow that ran the action around 24 June, and review recent runs for a workflow named "Run Copilot" that you did not add. The summary also says encrypted stolen data was uploaded to public repositories on victims' accounts, labeled "Alright Lets See If This Works", with more than 500 found.

What to do now

  1. Remove the packages from lockfiles, internal mirrors, build caches, container images and runners before rotating anything. Microsoft's advice, as relayed in the summary, is to treat developer machines and CI that installed infected versions as compromised.
  2. Rotate GitHub tokens, npm tokens, cloud keys and Kubernetes secrets from a clean machine.
  3. If you used the semantic-release action by tag, audit the runs from 24 June and rotate OIDC-linked and personal access tokens those runs could reach.
  4. List every package your account can publish and look for versions you did not release. The worm republishes every package a victim can access, and the summary says it bypasses npm two-factor authentication.

How this could have been avoided

  • Pin actions to a full commit SHA. The action attack worked by moving version tags, which a SHA reference ignores.
  • Remove long-lived npm tokens. A leaked token was the likely way in, and token publishing skipped two-factor checks. Use trusted publishing bound to one workflow, with a protected environment.
  • Treat binding.gyp as install-time code. A scanner that only reads lifecycle hooks in package.json misses it, so inspect native build files too.
  • Stop editors from auto-running project tasks. Set task.allowAutomaticTasks to off in VS Code and open unknown repositories in restricted mode.
  • Keep secrets out of reach of the runner. The malware pulled secrets from Actions runner memory, so scope each job to the minimum.

Try it yourself

Click through it at your own pace, or open it full screen.

Quick check

Why did pinning an action to a version tag not protect users here?

Tags can be moved. Attackers redirected several tags to a malicious commit, so a workflow that trusted the tag ran the attacker's code. A full commit SHA cannot be redirected.

Why is binding.gyp a problem for lifecycle-hook scanners?

It starts a native build at install time without a preinstall or postinstall entry, so tools that only inspect those hooks see nothing unusual.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.