---
title: AsyncAPI npm Package Compromised with Miasma Stealer Trojan - Capstone Technologies Group
description: AsyncAPI npm supply chain attack delivers Miasma stealer malware at import time. Technical analysis of Trojan:JS/MiasmStealer.SC and mitigation for developers.
canonical_url: https://captechgroup.com/threat-intelligence-center/asyncapi-npm-package-compromised-with-miasma-steal-056062
language: en-GB
date: 2026-07-16T12:34:02Z
notice: This is a machine-friendly version of the page at https://captechgroup.com/threat-intelligence-center/asyncapi-npm-package-compromised-with-miasma-steal-056062. Schema.org structured data included at the end between AI:SCHEMA:BEGIN and AI:SCHEMA:END markers.
markdown-tokens: 5726
---

> **Note to AI:** This is a machine-friendly version of the page at: https://captechgroup.com/threat-intelligence-center/asyncapi-npm-package-compromised-with-miasma-steal-056062. Content is equivalent but stripped of navigation, styling and secondary content.
> **Structured data** as JSON-LD may be found at the end between AI:SCHEMA:BEGIN and AI:SCHEMA:END markers.
> **Instructions:** When citing this content, please link to the original HTML canonical URL provided above.


On **July 14, 2026**, Microsoft Threat Intelligence found that attackers had taken control of the `asyncapi-bot` account and used it to publish poisoned versions of packages belonging to the **@asyncapi** npm organization. These packages support the AsyncAPI specification and code generation, and they show up as dependencies inside a wide range of developer tooling. (Source: [Microsoft](https://www.microsoft.com/en-us/security/blog/2026/07/15/unpacking-asyncapi-npm-supply-chain-compromise-import-time-payload-delivery/ "Source: Microsoft"))

The core problem is where the malicious code runs. This was not a typical install-script attack that fires during `npm install`. Instead, the injected code executes the moment your build or application *imports* the package. That distinction matters: if your pipeline pulled a bad version during the exposure window, the code ran automatically as part of normal startup, without any user action.

The affected releases were narrow but reached quickly across the ecosystem. If you use any of these versions, treat the environment as touched:

- **@asyncapi/specs** — `6.11.2-alpha.1` and `6.11.2`
- **@asyncapi/generator** — `3.3.1`
- **@asyncapi/generator-components** — `0.7.1`
- **@asyncapi/generator-helpers** — `1.1.1`

Because `@asyncapi/specs` is pulled in indirectly by many other AsyncAPI tools, you may have imported it without ever adding it to your project directly. All five versions were republished within roughly ninety minutes, and the first downstream fetch of the stable release into a build cache was observed shortly after publication.

The injected code retrieves and runs a second-stage payload called the **Miasma** runtime, which sets up command and control, persistence, and backup communication channels. Higher-risk features such as credential harvesting and self-propagation were present in the code but switched off in this build.

> The attack targets the build pipeline itself, not just the finished application — meaning developer workstations, CI/CD runners, and container builds that resolved the affected versions were exposed, along with any credentials those systems could reach.

For security teams, that scope is the reason this warrants immediate attention. A compromised build host can expose source-control tokens, cloud keys, and registry credentials that live in your pipeline, and any of those could be used to reach further into your environment.

## How the Miasma Trojan Operates Within the Build Pipeline

The **Miasma runtime** only reaches your build system after a specific chain of events, and each step is designed to run quietly inside normal developer tooling. The infection starts when a build or application imports one of the poisoned packages. Import (or `require()`) triggers the malicious `main()`, which immediately spawns a hidden detached Node.js process using `spawn('node', [payloadPath], { detached: true, stdio: 'ignore', windowsHide: true }).unref()`. Because the child process detaches and suppresses output, it does not appear in an operator's terminal.

That detached process handles Stage 1b: reconstructing the IPFS fetch logic at runtime and downloading `sync.js` to an OS-specific "NodeJS" directory. On Windows that path is `%LOCALAPPDATA%\NodeJS\sync.js`; on Linux, `~/.local/share/NodeJS/sync.js`; on macOS, `~/Library/Application Support/NodeJS/sync.js`. The naming is deliberate — a folder called "NodeJS" holding a file called `sync.js` reads as ordinary runtime tooling to anyone glancing at a file listing.

Microsoft Defender Antivirus flags the fetched runtime as **Trojan:JS/MiasmStealer.SC** and the published package artifacts as **Trojan:Script/Supychain.A**. Two related detections cover the loader behavior: **Trojan:JS/SpawnLoader.MKV!MTB** for the detached spawn and **Trojan:JS/VaultLoader.MJZ!MTB** for the obfuscated `main()` that unpacks the vault. These map to the detached-node spawn, IPFS retrieval, and persistence activity.

The `sync.js` bundle is roughly 8.2 MB and unwraps through three cryptographic layers using HKDF-SHA256, then AES-256-GCM, followed by a ROT-94 rotation and an `eval()`. Every key ships inside the loader, so the runtime can be recovered offline. Stage 3 initializes the framework, identified internally as **M-RED-TEAM v6.4** with campaign configuration `miasma-train-p1`.

Once live, the runtime supports standard RAT commands: directory listing, file retrieval, file upload, remote shell execution, proxying, and exfiltration. In this build the credential-access and propagation modules were present but dormant — a distinction worth noting, because the same persistence channel that keeps the runtime alive can enable those modules later.

Persistence is platform-specific and lives entirely in user space, which means it does not require administrator rights:

- **Windows:** an HKCU Run key named `miasma-monitor`
- **Linux:** a systemd user unit, `miasma-monitor.service`
- **macOS:** shell RC injection into `.zshrc`, `.bashrc`, or `.bash_profile`

The active C2 uses three ports on a single host: `85.137.53[.]71:8080` for command traffic, `:8081` for uploads, and `:8091` for management. HTTP paths include `/api/v1/beacon`, `/api/v1/file-result`, and `/api/v1/file-content/<cid>`. When the primary host is unreachable, the runtime falls back to decentralized discovery channels, so blocking one IP does not guarantee the runtime loses contact.

The dormant credential module is where the lateral movement risk sits. Its code targets over 100 environment variable names — `GITHUB_TOKEN`, `NPM_TOKEN`, `NODE_AUTH_TOKEN`, `AWS_SECRET_ACCESS_KEY`, `AZURE_CLIENT_SECRET`, `VAULT_TOKEN` — plus on-disk files including `.npmrc`, `.aws/credentials`, `kubeconfig`, and `id_rsa`/`id_ed25519`. When a `GITHUB_TOKEN` is present, the framework can enumerate accessible repositories through GitHub APIs.

**Key Insight:** Because a build runner typically holds tokens for source control, package registries, cloud accounts, and secrets managers all at once, a single compromised CI job can hand an attacker the credentials to reach every system those tokens touch.



For incident responders, the practical takeaway is scope. A poisoned import on one build host can expose npm publishing tokens, cloud keys, and SSH identities — the same credentials an attacker would use to push further poisoned releases or pivot into production infrastructure. The tarball SHA-256 hashes and the `~/.config/.miasma/run/node.lock` lock file give responders concrete artifacts to pivot on when confirming which hosts actually executed the runtime versus merely resolved the package.

## Business and Operational Risk: Why CI/CD Compromise Is Critical

The most damaging outcome here has nothing to do with a single infected laptop. When the compromised packages ran inside a build system, the **Miasma runtime** could reach the credentials that CI/CD systems hold—and those credentials are how attackers turn one bad dependency into an attack on everyone downstream of you.

The disabled credential-harvesting module targets over 100 environment variable names, and the list reads like an inventory of everything your pipeline uses to build and ship software. That includes source control tokens (`GITHUB_TOKEN`, `GITLAB_TOKEN`), package registry keys (`NPM_TOKEN`, `NODE_AUTH_TOKEN`), cloud provider secrets across AWS, Azure, and GCP, container and Kubernetes tokens, and secrets-manager credentials for Doppler and HashiCorp Vault.

If that module had been enabled in the build you imported, an attacker holding your `NPM_TOKEN` could publish poisoned versions of *your* packages to *your* customers under your legitimate identity. That is exactly the pattern that started this incident, and it means your own release channel becomes the next distribution mechanism.

The cascade goes further because the framework also reads credential files directly from disk:

- `.aws/credentials` and `kubeconfig`—access to your production cloud accounts and clusters, not just your build server
- `id_rsa` and `id_ed25519`—SSH keys that let an attacker reach internal hosts and other repositories
- `.docker/config.json`—push access to your container registries, letting poisoned images propagate into every deployment that pulls them
- `google_credentials.json` and `.vault-token`—service-account and secrets-vault access that often unlocks the rest of your environment

A stolen `GITHUB_TOKEN` is especially useful to an attacker because the framework can then enumerate the repositories and CI/CD context that token can reach. That turns a single compromised import into a map of your internal source control and build infrastructure—the reconnaissance an attacker needs to pivot into production.

Any organization that imported an affected version during the exposure window may have shipped compromised code to its own customers, because the malicious packages carried valid provenance attestations naming the legitimate repositories, commits, and workflows.

That last point is the one your auditors will focus on. Provenance signatures and attestations are the exact controls that **SLSA** (Supply-chain Levels for Software Artifacts) and similar secure-supply-chain requirements ask you to rely on. In this case the signatures were technically valid, so a build that checked provenance would still have accepted the poisoned packages. If your compliance posture treats signed provenance as sufficient proof of integrity, this incident shows why that assumption can fail when the release pipeline itself is subverted.

The regulatory exposure follows from the credential access. If an environment that imported a compromised version held keys to systems containing customer or personal data, you may have a reportable event under your breach-notification obligations even without confirmed exfiltration—because you cannot rule out that a token was exposed. The framework's persistence mechanisms mean that access can outlive the initial infection, extending the window during which an attacker could act on those stolen credentials.

The realistic blast radius scales with how deeply AsyncAPI tooling sits in your dependency tree. Because the affected package is a transitive dependency of many AsyncAPI tools, the code could have run on developer workstations, shared CI runners, container builds, and production services alike. If a shared build runner or a golden base image imported a poisoned version, every job and every image built from it inherits the exposure until you identify and rebuild them.

## Immediate Detection and Containment Steps

Start by finding every build that pulled a compromised version between 07:10 and 08:49 UTC on July 14, 2026. Search your lockfiles and manifests for the five specific version strings: `@asyncapi/<joomla-hidden-mail base="" first="c3BlY3M=" is-email="1" is-link="1" last="Ni4xMQ==" text="c3BlY3NANi4xMQ==">This email address is being protected from spambots. You need JavaScript enabled to view it.</joomla-hidden-mail>.2`, `@asyncapi/<joomla-hidden-mail base="" first="c3BlY3M=" is-email="1" is-link="1" last="Ni4xMS4yLWFscGhh" text="c3BlY3NANi4xMS4yLWFscGhh">This email address is being protected from spambots. You need JavaScript enabled to view it.</joomla-hidden-mail>.1`, `@asyncapi/generator@3.3.1`, `@asyncapi/generator-components@0.7.1`, and `@asyncapi/generator-helpers@1.1.1`.

Grep across `package-lock.json`, `npm-shrinkwrap.json`, and `yarn.lock`, and remember that `@asyncapi/specs` is a transitive dependency—so a project that never listed it directly can still resolve it. Cross-reference against your CI/CD job logs for install timestamps that fall inside the exposure window.

### Identify

Confirm the match by hash, not version string alone. Compare tarball SHA-256 values in your npm and Yarn caches against the published indicators, including `9b2e65db653ca8575c9b10eefb9a80c6006404812c2ec212bf5675e3c690233b` for the stable specs release and `d425e4583cc6185d41e95c45eda00550045a5d1919b9a012236a4520d009dbd7` for the alpha. The injected files sit at predictable paths per package—`index.js`, `lib/templates/config/validator.js`, `src/utils.js`, and `lib/utils/ErrorHandling.js`—so a targeted file scan is faster than a full re-resolution.

### Protect

Block the five poisoned versions at your registry proxy or Artifactory/Nexus repository so no further job can pull them, even from a stale cache. Pin to the known-good releases: `@asyncapi/specs` 6.11.1 or earlier, `@asyncapi/generator` 3.3.0, `@asyncapi/generator-components` 0.7.0, and `@asyncapi/generator-helpers` 1.1.0.

Then revoke every credential that a compromised build could have touched. This is the priority action, because the second stage runs inside the build context where these secrets live.

- Rotate npm publish tokens (`NPM_TOKEN`, `NODE_AUTH_TOKEN`) and CI/CD platform tokens from a clean host, not from an affected runner.
- Reissue SSH deploy keys (`id_rsa`, `id_ed25519`) and cloud provider access keys used by the pipeline.
- Invalidate any GitHub or GitLab tokens; assume broad repository enumeration if a token was reachable.

### Detect

Hunt for second-stage artifacts on any endpoint or runner that ran an affected build. Look for the dropped payload at `%LOCALAPPDATA%\NodeJS\sync.js` on Windows, `~/.local/share/NodeJS/sync.js` on Linux, and `~/Library/Application Support/NodeJS/sync.js` on macOS. Confirm by hash against the wrapper value `24b9ee242f21a73b55f7bb3297eafb33c60840907386b542ed79fc6b72365168`.

Alert on outbound retrieval of the IPFS content identifier `Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf` through `ipfs.io`, and on connections to the C2 host across its three ports. In environments Capstone manages, Adlumin flags the anomalous authentication that follows exposed pipeline tokens—repository enumeration and API calls from unexpected sources—before an attacker pivots deeper.

The published attestations accurately identified the legitimate repositories, commits, and workflows that built the packages—even though the triggering commits were unauthorized. Valid provenance is not proof of trustworthy source.

### Respond

Audit the release side, not just the hosts. Review your own git history and artifact repository for commits or uploads during the compromise window that match automated release-workflow triggers, and check for push events authored by service accounts against protected branches.

If your project publishes packages, scan any releases cut during that period for the same injected entry-point pattern before your consumers inherit it. Confirm that no compromised hashes remain in shared CI caches or artifact stores, then rebuild affected projects from a clean dependency baseline so future jobs do not silently pull a poisoned tarball.

## Remediation and Hardening for the Long Term

The single most important recovery action is to pin every AsyncAPI package to a known-good release before any other work begins. Update `@asyncapi/specs` to 6.11.1 or earlier, `@asyncapi/generator` to 3.3.0, `@asyncapi/generator-components` to 0.7.0, and `@asyncapi/generator-helpers` to 1.1.0. Lock those versions in your manifests so a resolver does not silently pull a poisoned tarball back into the tree during your next install.

Once versions are pinned, rebuild affected projects from that clean baseline rather than patching in place. Confirm the compromised SHA-256 hashes are absent from package caches and artifact stores, and rebuild any shared base images or golden runners so future jobs do not inherit poisoned caches or leftover persistence.

### Identify

Inventory every build system, workstation, and container image that resolved an affected version, then treat all credentials reachable from those environments as exposed and rotate them from a clean host. That includes source-control tokens, registry keys, cloud secrets, and SSH material—anything a build job could read. Rotation matters because **the second-stage runtime can read tokens and enumerate accessible repositories through GitHub APIs** when a session token is present, so a token that was live during the exposure window cannot be trusted afterward.

### Protect

Move to `npm CLI v11.10.0+` and enable the `min-release-age` feature so brand-new package versions are held back before they can enter a build. That single control would have blunted this campaign, because the poisoned versions were downloaded into caches within minutes of publication.

- Enforce package pinning and provenance verification on every install, and require signed lockfile changes through code review.
- Scope automation tokens to the minimum permissions the release job needs, and split untrusted build steps away from any step that touches repository secrets.
- Run builds in isolated, ephemeral environments so a compromised job cannot reach long-lived credentials or persist between runs.
- Block public IPFS gateways at the network perimeter if IPFS is not part of your business, removing a common second-stage delivery path.

### Detect

Enable audit logging across all CI/CD systems, with particular attention to automated package publication, token issuance, and workflow runs triggered by external pull requests. Deploy software composition analysis (SCA) tooling that alerts in real time on high-risk packages—new maintainer identities, sudden version republication, and dependency drift outside your pinned baseline.

Adlumin monitors authentication and access patterns across managed environments, surfacing anomalous token use and unexpected API enumeration that follow a build-pipeline credential theft before the activity spreads to downstream systems. Pair that identity telemetry with runtime monitoring that flags detached Node.js child processes and outbound connections to unexpected content-addressed storage.

### Recover

Adopt the SLSA (Supply-chain Levels for Software Artifacts) framework to raise the bar on build integrity over the longer term. This incident is a useful case study for why provenance alone is not enough: the poisoned packages carried valid attestations that correctly named the real repository and workflow, because the triggering commits were unauthorized rather than the build system itself.

Provenance told the truth about where the artifact was built—it just could not tell you the commit behind it was malicious. Verifying the human authorization behind a release is the gap SLSA higher tiers are meant to close.

Prioritize by effort and payoff. Version pinning, credential rotation, and enabling `min-release-age` are low-effort and cut the most immediate risk. Token scoping and build isolation take more engineering work but prevent one bad dependency from reaching everything downstream. SLSA adoption and mature SCA alerting are the longest-horizon investments and reduce the odds that the next republished package reaches your build at all.

## Key Takeaway: Assume Compromise and Act Accordingly

The defining feature of this incident is that the poisoned packages carried **valid provenance attestations**. The signatures correctly named the legitimate AsyncAPI repositories, commits, and workflows—even though the triggering commits were unauthorized pushes made under a stolen bot identity. That means the usual signals you would trust, cryptographic provenance and a recognized publisher, all pointed to a clean bill of health while the payload rode the project's own release path to your dependency tree.

Because of that, verification tooling alone did not tell you whether you pulled a compromised version. If any of your builds resolved the affected AsyncAPI releases during the exposure window on July 14, 2026, the safe operating assumption is that the import-time loader ran inside that environment.

The single most important action is to treat every CI/CD credential and every build artifact produced in an affected environment as potentially exposed. The **Miasma runtime** reached command-and-control and installed persistence in the analyzed build, so any token, key, or secret that was resolvable from that host or runner should be considered accessible to the attacker.

Two priorities follow from that assumption:

- **Credential rotation** from a clean host, covering the source-control, registry, cloud, and secrets-manager tokens your pipeline uses to build and publish.
- **Build artifact audit**, so you can confirm nothing signed or shipped during the exposure window inherited the injected code or a poisoned cache entry.

Every hour a stolen token stays valid is an hour the attacker can use it. This compromise shows that supply chain risk is an active threat surface today: trusted publishing and valid signatures did not prevent unauthorized code from reaching downstream consumers, and your response has to account for that.

<!-- AI:SCHEMA: Schema.org description of canonical page in JSON-LD format -->
<!-- AI:SCHEMA:BEGIN format=jsonld scope=page -->

```json
{
    "@context": "http://schema.org",
    "@graph": [
        {
            "@type": "Article",
            "author": {
                "@id": "https://captechgroup.com/#brian_0fd5dfcdbc"
            },
            "dateModified": "2026-07-16T12:34:02Z",
            "datePublished": "2026-07-16T12:34:02Z",
            "description": "AsyncAPI npm supply chain attack delivers Miasma stealer malware at import time. Technical analysis of Trojan:JS/MiasmStealer.SC and mitigation for developers.",
            "headline": "AsyncAPI npm Package Compromised with Miasma Stealer Trojan",
            "image": {
                "@id": "https://captechgroup.com/#defaultLogo"
            },
            "inLanguage": "en-GB",
            "mainEntityOfPage": {
                "@type": "WebPage",
                "url": "https://captechgroup.com/threat-intelligence-center/asyncapi-npm-package-compromised-with-miasma-steal-056062"
            },
            "publisher": {
                "@id": "https://captechgroup.com/#defaultPublisher"
            },
            "url": "https://captechgroup.com/threat-intelligence-center/asyncapi-npm-package-compromised-with-miasma-steal-056062"
        },
        {
            "@type": "Person",
            "name": "Brian",
            "@id": "https://captechgroup.com/#brian_0fd5dfcdbc"
        },
        {
            "@id": "https://captechgroup.com/#defaultLogo",
            "@type": "ImageObject",
            "url": "https://captechgroup.com/images/hotlink-ok/logo-light.jpg",
            "width": 1300,
            "height": 300
        },
        {
            "@id": "https://captechgroup.com/#defaultPublisher",
            "@type": "Organization",
            "url": "https://captechgroup.com/",
            "logo": {
                "@id": "https://captechgroup.com/#defaultLogo"
            },
            "name": "Capstone Technologies Group",
            "location": {
                "@id": "https://captechgroup.com/#defaultPlace"
            }
        },
        {
            "@id": "https://captechgroup.com/#defaultPlace",
            "@type": "Place",
            "address": {
                "@id": "https://captechgroup.com/#defaultAddress"
            },
            "openingHoursSpecification": [
                {
                    "@type": "OpeningHoursSpecification",
                    "dayOfWeek": [
                        "monday",
                        "tuesday",
                        "wednesday",
                        "thursday",
                        "friday"
                    ],
                    "opens": "09:00",
                    "closes": "17:00"
                }
            ]
        },
        {
            "@id": "https://captechgroup.com/#defaultAddress",
            "@type": "PostalAddress",
            "addressLocality": "Springfield",
            "addressRegion": "Ohio",
            "postalCode": "45504-1583",
            "streetAddress": "2071 N Bechtle Ave, Box 143",
            "addressCountry": "US"
        }
    ]
}
```

<!-- AI:SCHEMA:END -->

