Research

AsyncAPI npm Packages Re-Compromised: @asyncapi/generator 3.3.1 and Three Others

RobertUpdated Jul 15, 20264 min read
Attestd API response showing risk_state critical and supply_chain.compromised true for @asyncapi/generator version 3.3.1, one of four AsyncAPI npm packages re-compromised eight months after the Shai-Hulud supply chain wave.

Four packages in the @asyncapi npm scope were re-compromised on July 14, 2026, with new malicious versions published between approximately 07:10 and 08:30 UTC. All four were yanked from the registry before 09:00 UTC.

These packages were previously compromised in the November 2025 Shai-Hulud supply chain wave. The July 2026 event is a separate re-publish, not a continuation of the earlier incident. The compromised versions are new: 3.3.1 for @asyncapi/generator, 0.7.1 for @asyncapi/generator-components, 1.1.1 for @asyncapi/generator-helpers, and 6.11.2 for @asyncapi/specs.

Attribution is unverified. The OSV advisories reference Shai-Hulud source material from November 2025. Behavioral notes in the Amazon Inspector OSV entries describe obfuscated require-time spawning in the July 2026 versions, but no named actor or campaign has been confirmed for this wave.

A note on the compromised_at field#

The Attestd API response shows compromised_at: 2025-11-24 for all four packages. That reflects the OSV advisory publish date, which was written for the November 2025 Shai-Hulud incident and reused for the July 2026 re-compromise under the same advisory IDs. It is not evidence that the 2026 versions were a November 2025 event. The npm publish timestamps for 3.3.1, 0.7.1, 1.1.1, and 6.11.2 confirm July 14, 2026 as the actual re-compromise date.

This is a known limitation of OSV-id reuse and worth being explicit about in any automated pipeline consuming the compromised_at field.

What Attestd returns#

bash
curl "https://api.attestd.io/v1/check?product=%40asyncapi%2Fgenerator&version=3.3.1" \
  -H "Authorization: Bearer $ATTESTD_API_KEY"
json
{
  "product": "@asyncapi/generator",
  "version": "3.3.1",
  "supported": true,
  "risk_state": "critical",
  "risk_factors": ["supply_chain_compromised"],
  "confidence": 0.95,
  "cve_ids": [],
  "supply_chain": {
    "compromised": true,
    "sources": ["agent", "osv"],
    "malware_type": "malware",
    "description": "Malicious code in @asyncapi/generator (npm)",
    "compromised_at": "2025-11-24T11:48:04Z"
  },
  "supply_chain_monitored": true
}

risk_state: critical driven entirely by supply_chain_compromised. No CVEs, no vulnerability record. A system checking only CVE state passes this version clean.

sources: ["agent", "osv"] on three of the four packages means the pipeline flagged these in real time, not only after OSV published an advisory. @asyncapi/specs shows sources: ["osv"] only, reflecting the different detection path for that package.

The clean current versions for all four:

PackageCompromisedClean
@asyncapi/generator3.3.13.3.0
@asyncapi/generator-components0.7.11.0.0
@asyncapi/generator-helpers1.1.11.1.0
@asyncapi/specs6.11.26.11.1

All clean versions return risk_state: none with supply_chain.compromised: false.

Why re-compromise matters as a pattern#

The November 2025 Shai-Hulud wave hit over 500 npm packages. The assumption after a wave like that is that the affected packages are remediated, the advisories are published, and defenders move on. The July 14 event suggests a different model: packages that were already compromised once remain targets, either because the same actor retains access or because a different actor uses the prior compromise as a blueprint.

A pipeline that only checks whether a package was affected by a named historical campaign would have passed the July 2026 versions of these packages as clean. The compromised_at timestamps reference November 2025. The new malicious versions are distinct publishes with distinct npm metadata. The detection signal for the re-compromise is the supply chain monitoring layer catching the new versions as they appeared, not a lookup against the November 2025 advisory list.

If the re-compromise pattern repeats, the implication for any security layer that treats historical supply chain events as closed incidents is that it is operating on a stale threat model.

Coverage#

All four packages are covered. The compromised versions return risk_state: critical with supply_chain.compromised: true. The clean current versions return risk_state: none with supply_chain.compromised: false. Responses above are live from the production API as of July 15, 2026.

The related package @asyncapi/generator-react-sdk (OSV MAL-2025-190637, compromised versions 1.1.5 and 1.1.4 from November 2025) is also covered and is being reviewed for July 2026 re-compromise versions.

API documentation: attestd.io/docs. Detection ledger: github.com/attestd-io/detection-ledger. Machine speed thesis: attestd.io/thesis.