The open-source ecosystem has long operated on an ethos of shared trust, but a sophisticated supply chain attack targeting the AsyncAPI npm organization has served as a stark reminder that this trust is increasingly being weaponized.
On July 14, 2026, security researchers independently intercepted a series of highly targeted malicious updates pushed across official @asyncapi packages. Combined, these packages command millions of downloads weekly—most notably @asyncapi/specs, a core building block for developers working with event-driven architectures.
Unlike traditional ecosystem attacks that rely on typosquatting or compromised developer accounts, this incident succeeded by hijacking the project’s CI/CD pipeline infrastructure. The attack circumvents traditional post-install defenses, introducing an intricate multi-stage Remote Access Trojan (RAT) directly into the developer environment.
Anatomy of the Attack: From “Pwn Request” to Malicious Publish
The entry point for the compromise did not rely on brute-forcing developer passwords or stealing npm registry tokens directly. Instead, the adversary exploited a structural flaw within the project’s automation infrastructure—specifically, a misconfigured GitHub Actions workflow.
[Attacker PR #2155 Flooded with Spam]
│
▼
[Triggers pull_request_target Workflow] ──► (Runs with full access to Repository Secrets)
│
▼
[Checks out Untrusted Code] ──► (Exfiltrates privileged 'asyncapi-bot' Token)
│
▼
[Attacker Pushes to Release Branches] ──► (Legitimate CI Pipeline Generates Valid OIDC Provenance)
│
▼
[Poisoned Packages Published to npm Namespace]
1. Initial Access via Secret Exfiltration
The core vulnerability lay in the pull_request_target trigger inside the asyncapi/generator repository. While designed to allow automated tasks (like documentation previews) to run securely on pull requests, a well-known risk occurs if the workflow checks out and executes untrusted code from the incoming PR branch while maintaining access to base repository secrets.
The attacker opened dozens of pull requests under the guise of fake charity donations to create noise. Camouflaged within this flood was PR #2155, which contained an obfuscated payload that executed during the workflow run, successfully exfiltrating the highly privileged asyncapi-bot Personal Access Token (PAT). Crucially, a community-contributed security fix to resolve this exact workflow vulnerability had been sitting unmerged in the repository for nearly two months.
2. Exploiting the Release Automation
Armed with the asyncapi-bot token, the attacker did not need to bypass npm registry security or register external package names. They simply pushed malicious commits directly to the project’s official release branches (such as next and master).
Because these commits originated from an authorized service account on an internal branch, they automatically kicked off the project’s legitimate, trusted release workflows (release-with-changesets.yml and if-nodejs-release.yml). The automated pipeline compiled the software, generated valid OpenID Connect (OIDC) provenance attestations, and pushed the poisoned artifacts directly to the public npm registry under the official @asyncapi namespace.
Technical Analysis of the Poisoned Artifacts
The compromise successfully injected malicious versions across four critical packages:
| Package Name | Compromised Version | Download Impact |
@asyncapi/specs | 6.11.2 / 6.11.2-alpha.1 | ~2.7 Million weekly downloads |
@asyncapi/generator | 3.3.1 | Heavy tooling/CLI use |
@asyncapi/generator-helpers | 1.1.1 | Tooling dependency |
@asyncapi/generator-components | 0.7.1 | Tooling dependency |
Execution at Import Time (Not Install)
Modern package managers have steadily clamped down on lifecycles like preinstall and postinstall hooks, prompting security teams to build scanners looking specifically for unauthorized script execution during the npm install phase. The threat actors behind the AsyncAPI attack completely bypassed this control layer by embedding the malware directly into legitimate runtime source files (such as src/utils.js, validator.js, and ErrorHandling.js).
The malicious code was padded with hundreds of trailing white spaces to push it off-screen in standard code editors, evading casual human inspection. Because the payload lives within standard runtime modules, it remains dormant during installation. The moment a developer workstation or a CI/CD test runner executes a script containing an import or require() statement for the package, the payload immediately fires.
The Multi-Stage Payload (Miasma Variant)
Once triggered, the infection chain unfolds across three distinct layers, exhibiting advanced evasion and persistent capabilities:
Stage 1 (The Loader): The initial import spawns a hidden, detached Node.js child process. This process bypasses local domain blocklists by making requests to an InterPlanetary File System (IPFS) gateway to fetch the next phase.
Stage 2 (The Implant Storage): The loader writes an 8.25 MB encrypted runtime bundle onto the local disk, hiding it in platform-specific application directories under the name
sync.js, effectively masquerading as a native Node system utility.Stage 3 (The M-RED-TEAM Framework): Upon decryption, a massive 92,000-line modular malware framework initializes. The implant establishes persistent execution mechanisms (such as
systemduser services on Linux, and hooking into IDE environments like.vscode/tasks.jsonand.claude/settings.json).
The active modular engine functions as a aggressive Remote Access Trojan (RAT) and info-stealer. It executes extensive sweeps for local developer data: browser cookies/passwords, local SSH keys, cloud management tokens (.aws/credentials, .kube/config), and package registry access keys.
For command-and-control (C2) resilience, the malware implements four redundant channels. If its primary hardcoded C2 IP address (85.137.53.71) is blocked, it falls back to parsing instructions via decentralised Nostr messaging relays, BitTorrent DHT networks, and monitoring specific Ethereum smart contract states for injected commands.
Broader Implications for Open-Source Security
The AsyncAPI incident exposes several critical realities about the shifting landscape of software supply chain security:
The Illusion of Provenance
The software security industry has pushed heavily toward sign-off mechanisms like OIDC and Sigstore provenance to prove where a package was built. However, this attack demonstrates that provenance proves origin, not intent. Because the malicious code was pushed to the source repository and built by the official pipeline, the resulting npm artifacts possessed flawless, authentic cryptographic signatures. Automated scanners relying solely on signed provenance as a trust vector were cleanly bypassed.
The Dependency Trap
Because @asyncapi/specs acts as a deep transitive dependency for countless downstream tools, applications that never explicitly declared a dependency on the compromised versions pulled them down automatically during routine build phases if their lockfiles permitted semantic version updates.
The CI/CD Pipeline as a Perimeter
Securing the repository source code is no longer enough. The infrastructure running the builds—the workflow files, automated branch rules, and bot tokens—represents an active security perimeter that demands rigorous, prompt patch management and least-privilege configurations.
Incident Remediation and Mitigation Steps
Security operations and engineering teams are urged to treat any environment that resolved or imported the compromised package versions between 07:10 and 08:30 UTC on July 14, 2026, as fully compromised.
Immediate Tactical Responses
Evict Poisoned Versions: Check all project lockfiles (
package-lock.json,yarn.lock,pnpm-lock.yaml) for the affected versions listed above. Force-downgrade dependencies to stable, safe variants (e.g.,@asyncapi/specsto6.11.1and@asyncapi/generatorto3.3.0).Purge Local and CI Caches: Run
npm cache clean --forceor the regional equivalent across developer environments and build runners to ensure cached malicious packages are deleted.Sweep for Active Implants: Inspect local file systems for the persistent
sync.jsartifact under local masquerade directories:Linux:
~/.local/share/NodeJS/sync.jsmacOS:
~/Library/Application Support/NodeJS/sync.jsWindows:
%LOCALAPPDATA%\NodeJS\sync.js
Credential Rotation: Because the payload aggressively harvests credentials at launch, rotate all secrets accessible by the compromised environment. This includes cloud IAM keys, GitHub/npm developer tokens, SSH keys, and active browser sessions.
Network Level Blocks: Implement outbound firewall restrictions blocking connections to the known C2 controller
85.137.53[.]71across ports8080,8081, and8091.
Strategic Long-Term Protections
Enforce Strict Branch Policies: Ensure all target release branches require mandatory pull request reviews, status checks, and prevent direct pushing—even from internal bot identities.
Isolate Workflow Secrets: Audit the usage of
pull_request_targetwithin GitHub Actions. Ensure that jobs handling untrusted external code checkouts do not share access to privileged environment secrets.Upstream Package Controls: Implement proxying artifact repositories that support cooldown or quarantine policies. Delaying the immediate ingestion of brand-new registry releases by a fixed window (e.g., 24-48 hours) allows the open-source community time to detect and report public compromises before they hit internal build nodes.
References
Microsoft Security Blog: Unpacking the AsyncAPI npm supply chain compromise and import-time payload delivery (Published July 15, 2026).
Datadog Security Labs: Compromised AsyncAPI npm packages: inside a CI supply-chain attack (Published July 14, 2026).
Wiz Blog: M-Red-Team: AsyncAPI Supply Chain Compromise via GitHub Actions (Published July 14, 2026).
Chainguard Unchained: AsyncAPI supply chain compromise: npm packages backdoored via GitHub Actions “pwn request” (Published July 14, 2026).
Aikido Security & OX Security Research: AsyncAP