Trinitite worm compromises @7nohe/openapi-react-query-codegen on npm

CriticalCompromisenpm

On 2026-08-28 an attacker published 10 malicious versions of @7nohe/openapi-react-query-codegen (~150K npm weekly downloads) in a ~20-minute window. Root cause: an issue_comment-triggered GitHub Actions release workflow without an author-association gate - any GitHub user could open a fork PR, comment npm publish, and the pipeline checked out the fork, ran pnpm install (executing the attacker's preinstall hook) with id-token: write and minted an npm OIDC trusted-publishing token to ship the poisoned versions. Payload is a "Trinitite: Sponsored by Preview 2 Effects" credential-stealer worm continuing the Mini Shai-Hulud / TeamPCP lineage.

Published 28 Aug 2026 · Updated 29 Aug 2026

At a glancenpm-2026-08-28-trinitite-openapi-react-query-codegen
1
Package tracked10 malicious versions

Every version named by the advisory is in the scanner, so a lockfile check finds it directly.

Severity
Critical
Type
Compromise
Published
28 Aug 2026
Last updated
29 Aug 2026
Ecosystems
npm
Threat actor
TeamPCP (attributed) - "Trinitite" campaign
Detected by
Aikido Security, SafeDep, GitHub Advisory Database
Also known as
Trinitite, Trinitite: Sponsored by Preview 2 Effects, Mini Shai-Hulud (openapi-react-query-codegen wave)

Compromise. A legitimate, already-used package, maintainer account, CI pipeline, or release tag was hijacked and a malicious version was published under a name people already depend on.

What happened

The full picture

On 2026-08-28 an attacker published 10 malicious versions of the popular npm package @7nohe/openapi-react-query-codegen (a TanStack Query codegen against OpenAPI schemas, ~150K npm weekly downloads) within a ~20-minute window. The payload is a self-propagating credential-stealing worm calling itself Trinitite: Sponsored by Preview 2 Effects - a direct continuation of the TeamPCP / Mini Shai-Hulud lineage tracked in Shai-Hulud (2025-09), Mini Shai-Hulud Wave 2 (2026-04-30), and Mini Shai-Hulud on AntV (2026-05-19).

Affected versions

VersionNote
0.5.4, 0.5.5Adjacent pair on the 0.5 release train
1.6.3, 1.6.4Adjacent pair on the 1.6 release train
2.2.1, 2.2.2Adjacent pair on the 2.2 release train
3.0.3, 3.0.4Adjacent pair on the 3.0 release train
0.0.0-365d4eb738d3146583431948d3ba6e27a32556beCommit-hash prerelease tag
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0abCommit-hash prerelease tag

Pairing an adjacent malicious version onto every major release train is the noteworthy detail: it catches consumers pinned to ^0.5, ^1.6, ^2.2 and ^3.0 alike, not just those tracking latest.

Root cause: unguarded issue_comment release trigger

The repository's release workflow was wired to fire on issue_comment events with types: [created] and no if: guard on the commenter. That is enough:

  1. Fork PR: attacker opens a pull request from a fork of 7nohe/openapi-react-query-codegen containing an arbitrary code change (in this case, a malicious preinstall hook added to package.json).
  2. Trigger comment: the attacker leaves the comment npm publish (or any similar keyword the workflow keys on) on that pull request. GitHub delivers an issue_comment event; the workflow fires.
  3. Fork checkout: the workflow checks out github.event.pull_request.head.sha - the attacker's fork, complete with its malicious preinstall hook.
  4. Preinstall runs: pnpm install (or npm install) executes the attacker-controlled preinstall. Because the workflow granted permissions: id-token: write at workflow scope for the trusted-publishing step, that permission is already in the environment when the preinstall runs.
  5. Mint OIDC token: the preinstall exchanges the workflow's OIDC identity for an npm publish token via the npm trusted-publishing endpoint.
  6. Publish: the preinstall then invokes npm publish ten times, once for each of the poisoned versions, all landing on the legitimate @7nohe/openapi-react-query-codegen package identity.

The maintainer's npm credentials were never touched. The trust chain that broke is the assumption that only maintainers can trigger the workflow, and that only maintainer-authored code will ever be checked out inside it.

Payload: "Trinitite" worm

On postinstall of any consumer install, the payload:

  • Reads local npm auth from ~/.npmrc, ~/.config/pnpm/rc, and NPM_TOKEN environment variables.
  • Reads local GitHub auth (gh CLI cache, GH_TOKEN, GITHUB_TOKEN, ~/.config/gh/hosts.yml).
  • Enumerates every npm package the current user has publish rights on via npm access ls-packages.
  • For each such package, attempts to publish a trojanised version carrying the same worm payload - the self-propagation step.
  • Creates a new attacker-controlled GitHub repository under whichever account the stolen token can reach, named <Touhou-character-name>-<Touhou-character-name>-<random-number> with the description set literally to Trinitite: Sponsored by Preview 2 Effects.
  • Commits the harvested credentials to that repository as results/doubletrinnys-{counter}-{timestamp}.json - an encrypted credential bundle plus its encryption key, mirroring the "double" naming used across earlier Shai-Hulud iterations.

Scope of downstream impact

Only @7nohe/openapi-react-query-codegen under the @7nohe scope shows the anomalous publish burst; other scoped packages did not receive suspicious publishes on 2026-08-28. Downstream: any consumer that installed a poisoned tarball between first publish and npm takedown - developer workstations and CI runners alike - must be treated as fully compromised, with every credential in reach of that environment rotated from a clean host.

Related tracked activity

wormcredential-theftci-cd-compromiseaccount-takeovermaintainer-takeover
Affected packages

1 package 10 versions

These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once. It runs in your browser and nothing is uploaded.

Impact

What it does if you installed it

  • Ten malicious @7nohe/openapi-react-query-codegen versions shipped to the npm public registry on 2026-08-28 within a ~20-minute window: 0.5.4, 0.5.5, 1.6.3, 1.6.4, 2.2.1, 2.2.2, 3.0.3, 3.0.4, plus two pre-release commit-hash tags 0.0.0-365d4eb738d3146583431948d3ba6e27a32556be and 0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab. The attacker paired each malicious release with an adjacent version across every major release train (0.5.x, 1.6.x, 2.2.x, 3.0.x) so that any consumer pinned to ^0.5, ^1.6, ^2.2, or ^3.0 at install time between 2026-08-28 publish and takedown resolved a compromised tarball
  • The upstream package is a code generator for TanStack Query (formerly React Query) hooks against an OpenAPI schema; ~150,000 npm weekly downloads at the time of compromise. Consumers are React / TypeScript teams generating typed API clients at build time - a population that resolves the package on every pnpm install / yarn install / npm install in CI
  • Attack chain: (1) attacker opened a pull request from a fork against 7nohe/openapi-react-query-codegen, (2) commented npm publish on the PR, (3) the repository's release workflow triggered on issue_comment with types: [created] fired without an if: gate on github.event.comment.author_association - so any GitHub user with a comment permission could invoke it, (4) the workflow checkouted the head SHA (the attacker's fork), (5) ran pnpm install which executed the attacker's preinstall hook, (6) held permissions: id-token: write for npm trusted publishing via OIDC, so the attacker's preinstall minted a short-lived npm publish token in-workflow, (7) used that token to publish 10 tarballs under the legitimate @7nohe/openapi-react-query-codegen identity
  • Payload behaviour ("Trinitite"): on postinstall, enumerates local npm auth (~/.npmrc, NPM_TOKEN) and every npm package the current user maintains, then attempts to publish trojanised versions of each of those packages using the harvested token - i.e. the worm self-propagates in the same shape as Shai-Hulud (2025-09) and Mini Shai-Hulud Wave 2 (2026-04-30). Exfiltrated credentials are committed to attacker-controlled GitHub repositories whose names combine two randomly-chosen Touhou Project character names plus a random number, with the repo description set literally to Trinitite: Sponsored by Preview 2 Effects, and each payload lands as results/doubletrinnys-{counter}-{timestamp}.json containing an encrypted credential bundle and its encryption key
  • Impact for downstream teams: any CI or developer workstation that ran pnpm install / yarn install / npm install for a project pinned to any of the 10 affected versions between 2026-08-28 first publish and npm takedown should be treated as fully compromised: npm tokens, GitHub tokens surfaced in the environment, and any other secrets present in the shell / CI runner context are considered exfiltrated. If the affected machine had publish rights to other packages under the developer's npm account, those packages may already carry their own trojanised republishes - the worm shape is the whole point
  • Only the @7nohe/openapi-react-query-codegen package under the @7nohe npm scope shows the anomalous publish burst; other packages under the same scope did not receive suspicious publishes on 2026-08-28. The maintainer's own npm credentials were not stolen - the takeover was via the CI workflow, not via account compromise
What to do

Clean-up steps

  1. Grep every lockfile (package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lock) and node_modules/@7nohe/openapi-react-query-codegen/package.json for exact versions 0.5.4, 0.5.5, 1.6.3, 1.6.4, 2.2.1, 2.2.2, 3.0.3, 3.0.4, 0.0.0-365d4eb738d3146583431948d3ba6e27a32556be, 0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab
  2. Pin @7nohe/openapi-react-query-codegen to a version PUBLISHED BEFORE 2026-08-28 that you have independently verified against the upstream Git tag (a downgrade to 3.0.2 / 2.2.0 / 1.6.2 / 0.5.3 depending on your release train). Rebuild lockfiles after the pin, and re-run pnpm install --frozen-lockfile / npm ci to guarantee the compromised tarball is evicted from every workspace
  3. If any developer or CI runner installed one of the 10 flagged versions: treat that machine as fully compromised. Rotate every credential reachable from that machine's environment - starting with the developer's npm auth token (npm token revoke <hash> for every token the user owns), then GitHub PATs / fine-grained tokens / SSH keys under the same user, then cloud provider CLI credentials (aws configure --profile <p>, gcloud auth login, az login), then any secret exported into the runner's environment for the affected job
  4. Audit every other npm package the affected developer publishes for a trojanised republish. The worm attempts to auto-publish to every package the compromised token can reach. npm view <pkg> versions --json and cross-check the latest version's publish time against the developer's intended release cadence; any version published in the same window as the compromise but not matching an expected release is suspect
  5. For maintainers of any repository that uses on: issue_comment to trigger a publish, deploy, or write-scope job: add an author-association gate immediately. Minimum viable check: if: contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association). Even better: require the comment on a PR the maintainer authored, not on any PR. pull_request_target and issue_comment are the two most-abused triggers for supply-chain compromises via fork PRs - both need author gates AND minimal permissions: blocks (contents: read at the top of the workflow, elevated only in the specific step that needs it)
  6. For maintainers using npm trusted publishing (OIDC id-token: write): the same author-association gate applies, and the id-token: write permission should never be granted at the workflow level - only at the specific step that runs npm publish. A fork checkout that runs pnpm install before the publish step must not have any token-minting scope in its environment
  7. Watch for the "Trinitite" IOCs: a new GitHub repository under any of your developers' accounts named <Touhou-name>-<Touhou-name>-<number> with description exactly Trinitite: Sponsored by Preview 2 Effects and a results/doubletrinnys-*.json file is a live indicator of a compromised token in that user's environment. Delete the repo and rotate the token that could have created it
  8. Anyone who previously mirrored @7nohe/openapi-react-query-codegen to an internal registry (Nexus, Artifactory, Verdaccio) must audit that mirror: internal caches routinely keep serving the poisoned tarballs after the npm public takedown. Force a re-sync from upstream once you have confirmed the malicious versions are no longer served publicly
References

Sources

npm-2026-08-28-trinitite-openapi-react-query-codegenBack to incidentsSubmit a correction
Am I affected?

Check your lockfile against this and every other incident.

Paste a lockfile and it is matched on your own device against every compromised version we track. Nothing is uploaded and there is no account.