# AsyncAPI npm Supply Chain Compromise: GitHub Actions pull_request_target Exploit Deploys Miasma RAT to Packages with 2.9M Weekly Downloads

> Attackers exploited a long-unpatched pull_request_target misconfiguration in the asyncapi/generator GitHub Actions workflow to exfiltrate a highly privileged npm publishing token belonging to the asyncapi-bot service account, then used it to publish five trojanized versions of four AsyncAPI npm packages (combined ~2.9M weekly downloads). The injected code runs on module import, downloads an encrypted multi-stage loader from IPFS, and deploys a remote-access trojan self-identified as "M-RED-TEAM v6.4" under the campaign tag miasma-train-p1, which beacons to an HTTP C2 server and maintains blockchain/decentralized fallback channels (Ethereum smart contract, Nostr relays, BitTorrent DHT, libp2p).

- **Published:** 2026-07-14T00:00:00Z
- **Last reviewed:** 2026-10-28T15:51:37.608Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-1320
- **ID:** TL-2026-1320
- **Severity:** CRITICAL
- **Category:** SUPPLY_CHAIN
- **Status:** ACTIVE
- **Actor:** M-RED-TEAM
- **Detections:** 9 · **IOCs:** 42 (full data via the Threadlinqs MCP server — Purple tier)

## Description

On 2026-07-14 at 05:08 UTC, an unknown threat actor opened 37 pull requests against the asyncapi/generator GitHub repository, the majority of which were decoy PRs proposing a fake charity donation page. One PR (#2155) contained JavaScript obfuscated behind roughly 1,000 bytes of leading whitespace that exploited the repository's pull_request_target GitHub Actions trigger. This trigger type runs workflows with access to base-repository secrets even when the workflow checks out attacker-controlled pull request code -- a known "pwn request" anti-pattern. A remediation PR (#2078/#2092) flagging this exact misconfiguration had been open and unmerged for 58-77 days (proposed 2026-04-29/05-17) at the time of the breach. The malicious workflow run completed at 05:16 UTC, exfiltrating a highly privileged Personal Access Token belonging to the asyncapi-bot service account to a dead-drop paste on rentry.co. Using the stolen token, the attacker pushed a malicious commit (3eab3ec9304aa26081358330491d3cfeb55cc245) directly to the next branch at 06:58 UTC, triggering the release workflow. The first three trojanized packages published at 07:10 UTC, with two additional compromised versions following between 07:51 and 08:28 UTC.

Five versions across four @asyncapi npm packages were backdoored: @asyncapi/specs (6.11.2 and 6.11.2-alpha.1, the highest-traffic package at ~2.7M weekly downloads alone), @asyncapi/generator (3.3.1), @asyncapi/generator-helpers (1.1.1), and @asyncapi/generator-components (0.7.1). Unlike npm supply-chain attacks that rely on postinstall lifecycle scripts, the malicious code was embedded directly inside runtime modules using three distinct injection techniques: whitespace obfuscation (roughly 880 padding spaces concealing payload inside legitimate function closures), direct inline injection prepended to index.js, and hex-variable obfuscation with base64-encoded string arrays via javascript-obfuscator with a custom base64 alphabet. This design ensures the payload fires on a simple require()/import call rather than only during npm install, evading defenses that only monitor lifecycle-script execution.

On import, the injected loader (Stage 1) spawns a detached Node.js child process (surviving parent termination, hidden from the user) that fetches an 8.2-8.25MB encrypted bundle (Stage 2) from IPFS (CIDs Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf for the specs payload and QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9 for the generator-family payload), writing it to disk as sync.js under platform-specific per-user Node.js directories. The bundle is decrypted using ECDH + HKDF-SHA256 key derivation with AES-256-GCM (plus an ASCII rotation-reversal step), yielding Stage 3: a roughly 92,000-line modular RAT framework that self-identifies in runtime comments as "M-RED-TEAM v6.4" and internally as build target "miasma-train-p1". A hardcoded fallback master key ("rt-vault-master-key-32b-aaaaaaaa") was found in plaintext in the payload. The compiled payload build timestamp (2026-07-14 04:10 UTC) precedes the compromise by roughly three hours, indicating pre-staged tooling.

The deployed implant establishes persistence via systemd user service (Linux: ~/.config/systemd/user/miasma-monitor.service), shell rc-file injection with the marker "### Node Auto-Update Script ###" (macOS/Linux), and an HKCU Run-key registry entry (Windows), alongside a lock file (~/.config/.miasma/run/node.lock or ~/.config/miasma/runnode.lock) to prevent duplicate execution. It beacons via HTTP to 85.137.53.71:8080 approximately every 30 seconds using per-victim derived encryption keys and a custom header (X-Miasma-Spawn-Chain), with companion ports 8081 (upload/exfiltration) and 8091 (proxy management) on the same host (RIPE block 85.137.53.0/24, AS43641, Netherlands). Decentralized fallback channels include an Ethereum smart contract on mainnet (0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710), Nostr relays (wss://relay.damus.io, wss://relay.nostr.com/), BitTorrent DHT bootstrap nodes (router.bittorrent.com:6881, dht.transmissionbt.com:6881), plus IPFS, libp2p, and mDNS -- a seven-channel failover communications stack.

Active/enabled capabilities observed in the recovered build include a remote shell handler executing arbitrary commands via child_process.exec() (blacklisting only the literal string "killall"), file operations sandboxed to a /sim-fs path, system reconnaissance (PATH, HOME, USER, HOSTNAME), and payload update retrieval from Nostr/Ethereum sources. Analysts identified an extensive but largely DISABLED credential-harvesting module covering 300+ target file paths: AWS credentials (~/.aws/*), SSH/GPG keys, npm tokens (~/.npmrc), GitHub CLI config, Kubernetes/Docker registry auth, browser-saved passwords and cookies (Chrome, Brave, Firefox, Edge), macOS Keychain, cryptocurrency wallets (Bitcoin, Ethereum, Solana), AI-tool credentials (Claude/Anthropic, Cursor), and password managers (Bitwarden, 1Password, KeePassXC). Also present but toggled off: self-propagation modules targeting npm, PyPI, and Cargo; AI-developer-tool poisoning hooks (Claude, VS Code, Gemini, Cursor); a metamorphic self-modification/evasion engine; security-product sandbox-evasion checks (CrowdStrike, SentinelOne, Microsoft Defender, CarbonBlack, Cylance, Osquery, Tanium, Qualys); and a dead-man-switch that would wipe local directories if credential revocation were detected. The recovered configuration additionally contained misleading/contradictory flags (safeMode: true, actualPersist: false, canaryPercent: 5) that code analysis found did not match actual call-graph behavior.

Attribution is unresolved. The payload self-identifies as "M-RED-TEAM v6.4" and shares artifact naming, obfuscation tooling (javascript-obfuscator custom-alphabet config), and infrastructure-naming conventions (miasma-test-org, miasma-monitor.service, Miasma-tagged Nostr relays) with the open-source "Miasma" toolkit released publicly in June 2026, as well as dead-drop URL slug patterns ("elzotebo") matching a prior PR-flood campaign researchers term "prt-scan." However, researchers at Wiz explicitly declined definitive attribution, and JFrog/SafeDep analysis found the AsyncAPI deployment differs substantially from the June 2026 Red Hat-wave Miasma campaign in runtime (vanilla Node.js vs. Bun), payload staging location (persistent per-user directories vs. /tmp), crypto primitives (secp256k1+AES-256-GCM vs. RSA-4096+AES-256-CBC), and C2 design (persistent encrypted HTTP channel vs. GitHub-repo-based exfiltration), suggesting a copy-paste/rebrand of prior tooling by a distinct or evolved operator rather than a like-for-like reuse.

Aikido Security detected and disclosed the compromised packages on 2026-07-14. Remediation guidance from responders (Aikido, Wiz, JFrog, SafeDep, Upwind) converges on: pin/downgrade to the last-known-clean versions (@asyncapi/specs@6.11.1, @asyncapi/generator@3.3.0, @asyncapi/generator-helpers@1.1.0, @asyncapi/generator-components@0.7.0); remove the compromised versions from lockfiles/manifests; treat build-host and developer credentials as fully compromised and rotate npm tokens, GitHub tokens (including write tokens for both asyncapi/generator and the related asyncapi/spec-json-schemas repository, which was separately compromised), SSH/signing keys, AWS credentials, and CI/CD secrets from clean machines; hunt for the sync.js drop file and OS-specific persistence artifacts on any system that merely imported the affected modules (installation alone is sufficient exposure, since the payload fires on require/import, not only on npm install); and purge the compromised alpha tarball from CDN/package-registry backing storage. Longer-term hardening includes eliminating pull_request_target on workflows with external PR checkout, dependency allowlisting/SBOM generation, and enhanced build-environment/package-integrity monitoring.

## MITRE ATT&CK

- T1199 Trusted Relationship
- T1195 Supply Chain Compromise
- T1059 Command and Scripting Interpreter
- T1106 Native API
- T1547 Boot or Logon Autostart Execution
- T1543 Create or Modify System Process
- T1546 Event Triggered Execution
- T1027 Obfuscated Files or Information
- T1140 Deobfuscate/Decode Files or Information
- T1497 Virtualization/Sandbox Evasion
- T1685 Disable or Modify Tools
- T1552 Unsecured Credentials
- T1555 Credentials from Password Stores
- T1528 Steal Application Access Token
- T1082 System Information Discovery
- T1518 Software Discovery
- T1071 Application Layer Protocol
- T1573 Encrypted Channel
- T1008 Fallback Channels
- T1105 Ingress Tool Transfer
- T1205 Traffic Signaling
- T1102 Web Service
- T1104 Multi-Stage Channels
- T1074 Data Staged
- T1567 Exfiltration Over Web Service
- T1020 Automated Exfiltration
- T1485 Data Destruction
- T1584 Compromise Infrastructure
- T1587 Develop Capabilities
- T1543.002 Create or Modify System Process
- T1543.001 Create or Modify System Process
- T1053.003 Scheduled Task/Job
- T1564.001 Hide Artifacts
- T1003.007 OS Credential Dumping
- T1614.001 System Location Discovery
- T1041 Exfiltration Over C2 Channel

## Sources

- [AsyncAPI npm Packages With 2M Weekly Downloads Compromised](https://cybersecuritynews.com/asyncapi-npm-packages-with-2m-weekly-downloads/)
- [AsyncAPI npm packages backdoored via GitHub Actions](https://www.aikido.dev/blog/asyncapi-npm-packages-backdoored-via-github-actions)
- [M-Red-Team: AsyncAPI Supply Chain Compromise via GitHub Actions](https://www.wiz.io/blog/m-red-team-asyncapi-supply-chain-compromise-via-github-actions)
- [AsyncAPI Packages Compromised with Miasma RAT](https://safedep.io/asyncapi-generator-supply-chain-attack-miasma-rat/)
- [Miasma Worm Returns to npm](https://research.jfrog.com/post/miasma-worm-returns-to-npm/)
- [Upwind's AsyncAPI npm Package Investigation Suggests Software Release Pipelines Are Becoming Prime Targets](https://newsblaze.com/business/security/upwinds-asyncapi-npm-package-investigation-suggests-software-release-pipelines-are-becoming-prime-targets_215681/)
- [Large amount of popular NPM packages compromised (Zapier, ENS, AsyncAPI, PostHog, Browserbase, and Postman)](https://forum.level1techs.com/t/large-amount-of-popular-npm-packages-compromised-zapier-ens-asyncapi-posthog-browserbase-and-postman/241416)

## Full data

Detection queries (Splunk SPL / Microsoft KQL / Sigma) and IOC values require the Threadlinqs MCP server (Purple tier): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-1320
