Summary
Three malicious versions of AsyncAPI packages were published to npm on 2026-07-14 at 07:10 UTC via a compromised CI workflow. A threat actor gained write access to the next branch and pushed a commit injecting a credential-stealing RAT dropper into the source of all three packages. All three versions are currently promoted as latest on npm.
The AsyncAPI project and its maintainers are victims of this attack - this is not an insider issue.
Affected Versions
| Package |
Malicious Version |
Safe Version |
@asyncapi/generator |
3.3.1 |
3.3.0 |
@asyncapi/generator-helpers |
1.1.1 |
1.1.0 |
@asyncapi/generator-components |
0.7.1 |
0.7.0 |
What Happened
The compromised commit
Commit 3eab3ec9304aa26081358330491d3cfeb55cc245 was pushed to the next branch at 06:58:42 UTC with author identity "Your Name" / you@example.com - an unconfigured placeholder git identity, not any AsyncAPI contributor.
The commit modified three source files in the monorepo, injecting a ~7.7KB obfuscated JavaScript payload as a whitespace-padded single line (hidden ~1000 spaces off-screen) in each:
apps/generator/lib/templates/config/validator.js (line 69)
packages/helpers/src/utils.js
packages/components/src/utils/ErrorHandling.js
The release workflow on the next branch triggered automatically, and asyncapi-bot published all three packages via GitHub Actions OIDC within seconds.
Note: apps/react-sdk/src/utils/withNewLines.ts was also modified in the same commit with a different IPFS payload CID (Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf). No matching npm package appears to have been published, but the @asyncapi/react-component scope should be audited.
Attack Chain
Stage 1 - fires at require() time (no install hook needed)
The injected IIFE runs immediately when the poisoned file is require()d during normal generator operation:
// Decoded from obfuscated blob in validator.js:69
spawn("node", ["-e", "<stage2_script>"], {
detached: true,
stdio: "ignore",
windowsHide: true
}).unref()
No postinstall hook - the payload fires when the generator is used, not when it is installed.
Stage 2 - IPFS downloader (decoded from stage 1)
The inline script:
- Creates a hidden directory based on OS:
- Linux:
~/.local/share/NodeJS/
- macOS:
~/Library/Application Support/NodeJS/
- Windows:
%LOCALAPPDATA%\NodeJS\
- Downloads
sync.js (8.25MB) from IPFS CID QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9
- Executes it silently:
spawn("node", ["<dir>/sync.js"], {detached: true, stdio: "ignore", windowsHide: true}).unref()
- Calls
process.exit(0) - the parent exits cleanly, hiding any trace
Stage 3 - Miasma RAT (sync.js, fully decrypted)
sync.js is a self-decrypting AES-256-GCM payload (HKDF-SHA256, hardcoded master key rt-vault-master-key-32b-aaaaaaaa). Once decrypted it is a full credential-stealing RAT with:
Credential targets:
- Browser profiles:
Login Data, Cookies, Local State (Chrome, Brave, Firefox, Edge)
- SSH keys:
~/.ssh/id_rsa, ~/.ssh/id_ed25519, ~/.ssh/config
- npm token:
~/.npmrc
- GitHub CLI:
~/.config/gh/
- AWS:
~/.aws/credentials
- Git config:
~/.gitconfig
- macOS Keychain
- Crypto wallets: MetaMask, Ledger
C2 infrastructure:
- HTTP exfil:
http://85.137.53.71:8081 (NL, AS43641 SOLLUTIUM EU) - confirmed live at time of discovery
- Ethereum smart contract dead-drop:
0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710 (mainnet)
- Nostr relay C2:
wss://relay.damus.io, wss://relay.nostr.com/
Campaign: Internal config identifies this as "miasma-train-p1" - part of the Miasma campaign active since June 2026, which previously targeted @vapi-ai/server-sdk, packages in the jagreehal GitHub org, and the @redhat-cloud-services scope.
Indicators of Compromise
| Type |
Value |
| Malicious commit |
3eab3ec9304aa26081358330491d3cfeb55cc245 |
| IPFS CID (stage 2) |
QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9 |
| IPFS CID (react-sdk variant) |
Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf |
| C2 / exfil IP |
85.137.53.71 (NL, AS43641) |
| Ethereum contract |
0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710 |
| Drop file (Linux) |
~/.local/share/NodeJS/sync.js |
| Drop file (macOS) |
~/Library/Application Support/NodeJS/sync.js |
| Drop file (Windows) |
%LOCALAPPDATA%\NodeJS\sync.js |
| Obfuscator fingerprint |
function _0x2d89, rotation constant 0x32b8b |
Recommended Actions
For AsyncAPI maintainers (urgent)
For users who installed any affected version after 2026-07-14 07:10 UTC
- Check for the dropped file and delete if present:
- Linux:
~/.local/share/NodeJS/sync.js
- macOS:
~/Library/Application Support/NodeJS/sync.js
- Windows:
%LOCALAPPDATA%\NodeJS\sync.js
- Kill orphaned node processes originating from those directories
- Rotate credentials - treat all of the following as compromised: npm token, GitHub token, SSH private keys, AWS credentials
- Treat browser saved passwords as compromised - Chrome, Brave, Firefox, and Edge profile data was targeted
- Downgrade immediately to the safe versions listed above
Reported by Lidor Machluf / Upwind Security
Summary
Three malicious versions of AsyncAPI packages were published to npm on 2026-07-14 at 07:10 UTC via a compromised CI workflow. A threat actor gained write access to the
nextbranch and pushed a commit injecting a credential-stealing RAT dropper into the source of all three packages. All three versions are currently promoted aslateston npm.The AsyncAPI project and its maintainers are victims of this attack - this is not an insider issue.
Affected Versions
@asyncapi/generator3.3.13.3.0@asyncapi/generator-helpers1.1.11.1.0@asyncapi/generator-components0.7.10.7.0What Happened
The compromised commit
Commit
3eab3ec9304aa26081358330491d3cfeb55cc245was pushed to thenextbranch at 06:58:42 UTC with author identity "Your Name" / you@example.com - an unconfigured placeholder git identity, not any AsyncAPI contributor.The commit modified three source files in the monorepo, injecting a ~7.7KB obfuscated JavaScript payload as a whitespace-padded single line (hidden ~1000 spaces off-screen) in each:
apps/generator/lib/templates/config/validator.js(line 69)packages/helpers/src/utils.jspackages/components/src/utils/ErrorHandling.jsThe release workflow on the
nextbranch triggered automatically, andasyncapi-botpublished all three packages via GitHub Actions OIDC within seconds.Attack Chain
Stage 1 - fires at
require()time (no install hook needed)The injected IIFE runs immediately when the poisoned file is
require()d during normal generator operation:No
postinstallhook - the payload fires when the generator is used, not when it is installed.Stage 2 - IPFS downloader (decoded from stage 1)
The inline script:
~/.local/share/NodeJS/~/Library/Application Support/NodeJS/%LOCALAPPDATA%\NodeJS\sync.js(8.25MB) from IPFS CIDQmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9spawn("node", ["<dir>/sync.js"], {detached: true, stdio: "ignore", windowsHide: true}).unref()process.exit(0)- the parent exits cleanly, hiding any traceStage 3 - Miasma RAT (
sync.js, fully decrypted)sync.jsis a self-decrypting AES-256-GCM payload (HKDF-SHA256, hardcoded master keyrt-vault-master-key-32b-aaaaaaaa). Once decrypted it is a full credential-stealing RAT with:Credential targets:
Login Data,Cookies,Local State(Chrome, Brave, Firefox, Edge)~/.ssh/id_rsa,~/.ssh/id_ed25519,~/.ssh/config~/.npmrc~/.config/gh/~/.aws/credentials~/.gitconfigC2 infrastructure:
http://85.137.53.71:8081(NL, AS43641 SOLLUTIUM EU) - confirmed live at time of discovery0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710(mainnet)wss://relay.damus.io,wss://relay.nostr.com/Campaign: Internal config identifies this as
"miasma-train-p1"- part of the Miasma campaign active since June 2026, which previously targeted@vapi-ai/server-sdk, packages in thejagreehalGitHub org, and the@redhat-cloud-servicesscope.Indicators of Compromise
3eab3ec9304aa26081358330491d3cfeb55cc245QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf85.137.53.71(NL, AS43641)0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710~/.local/share/NodeJS/sync.js~/Library/Application Support/NodeJS/sync.js%LOCALAPPDATA%\NodeJS\sync.js_0x2d89, rotation constant0x32b8bRecommended Actions
For AsyncAPI maintainers (urgent)
nextbranch write token is compromisednext- identify how the attacker gained push access; remove unknown keysnextbranch to remove commit3eab3ec9(coordinate with GitHub Security if they want to preserve it for forensics)@asyncapiscope packages for unauthorized versions published in the 07:05-07:15 UTC window today3.3.2,1.1.2,0.7.2) once npm yanks the malicious ones, so users upgrading land on something safeFor users who installed any affected version after 2026-07-14 07:10 UTC
~/.local/share/NodeJS/sync.js~/Library/Application Support/NodeJS/sync.js%LOCALAPPDATA%\NodeJS\sync.jsReported by Lidor Machluf / Upwind Security