Trinitite worm compromises @7nohe/openapi-react-query-codegen on npm
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
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)
- Source
- github.com
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.
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
| Version | Note |
|---|---|
0.5.4, 0.5.5 | Adjacent pair on the 0.5 release train |
1.6.3, 1.6.4 | Adjacent pair on the 1.6 release train |
2.2.1, 2.2.2 | Adjacent pair on the 2.2 release train |
3.0.3, 3.0.4 | Adjacent pair on the 3.0 release train |
0.0.0-365d4eb738d3146583431948d3ba6e27a32556be | Commit-hash prerelease tag |
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab | Commit-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:
- Fork PR: attacker opens a pull request from a fork of
7nohe/openapi-react-query-codegencontaining an arbitrary code change (in this case, a maliciouspreinstallhook added topackage.json). - Trigger comment: the attacker leaves the comment
npm publish(or any similar keyword the workflow keys on) on that pull request. GitHub delivers anissue_commentevent; the workflow fires. - Fork checkout: the workflow checks out
github.event.pull_request.head.sha- the attacker's fork, complete with its maliciouspreinstallhook. - Preinstall runs:
pnpm install(ornpm install) executes the attacker-controlledpreinstall. Because the workflow grantedpermissions: id-token: writeat workflow scope for the trusted-publishing step, that permission is already in the environment when the preinstall runs. - Mint OIDC token: the preinstall exchanges the workflow's OIDC identity for an npm publish token via the npm trusted-publishing endpoint.
- Publish: the preinstall then invokes
npm publishten times, once for each of the poisoned versions, all landing on the legitimate@7nohe/openapi-react-query-codegenpackage 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, andNPM_TOKENenvironment variables. - Reads local GitHub auth (
ghCLI 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 toTrinitite: 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
- Shai-Hulud lineage: the Trinitite payload shape (harvest → self-publish → GitHub exfil) is the same family as Shai-Hulud (2025-09), Mini Shai-Hulud Wave 2 (2026-04-30), and Mini Shai-Hulud on AntV (2026-05-19); attribution circle around TeamPCP.
issue_commenttrigger abuse: the same class of unguarded workflow trigger has been used against other npm supply-chain targets (Codfish semantic-release-action GitHub Actions hijack (2026-06-24)); the pattern to look for in your own repos ison: issue_commentORon: pull_request_targetwith any write-scopepermissions:and no author-association gate.- Discovery credits: Aikido Security and SafeDep. GHSA-rg27-qr39-ch6w tracks the advisory.
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.
What it does if you installed it
- Ten malicious
@7nohe/openapi-react-query-codegenversions 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 tags0.0.0-365d4eb738d3146583431948d3ba6e27a32556beand0.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.0at 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 installin CI - Attack chain: (1) attacker opened a pull request from a fork against
7nohe/openapi-react-query-codegen, (2) commentednpm publishon the PR, (3) the repository's release workflow triggered onissue_commentwithtypes: [created]fired without anif:gate ongithub.event.comment.author_association- so any GitHub user with a comment permission could invoke it, (4) the workflowcheckouted the head SHA (the attacker's fork), (5) ranpnpm installwhich executed the attacker's preinstall hook, (6) heldpermissions: id-token: writefor 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-codegenidentity - 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 toTrinitite: Sponsored by Preview 2 Effects, and each payload lands asresults/doubletrinnys-{counter}-{timestamp}.jsoncontaining an encrypted credential bundle and its encryption key - Impact for downstream teams: any CI or developer workstation that ran
pnpm install/yarn install/npm installfor 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-codegenpackage under the@7nohenpm 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
Clean-up steps
- Grep every lockfile (
package-lock.json,pnpm-lock.yaml,yarn.lock,bun.lock) andnode_modules/@7nohe/openapi-react-query-codegen/package.jsonfor exact versions0.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 - Pin
@7nohe/openapi-react-query-codegento a version PUBLISHED BEFORE 2026-08-28 that you have independently verified against the upstream Git tag (a downgrade to3.0.2/2.2.0/1.6.2/0.5.3depending on your release train). Rebuild lockfiles after the pin, and re-runpnpm install --frozen-lockfile/npm cito guarantee the compromised tarball is evicted from every workspace - 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 - 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 --jsonand 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 - For maintainers of any repository that uses
on: issue_commentto 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_targetandissue_commentare the two most-abused triggers for supply-chain compromises via fork PRs - both need author gates AND minimalpermissions:blocks (contents: readat the top of the workflow, elevated only in the specific step that needs it) - For maintainers using npm trusted publishing (OIDC
id-token: write): the same author-association gate applies, and theid-token: writepermission should never be granted at the workflow level - only at the specific step that runsnpm publish. A fork checkout that runspnpm installbefore the publish step must not have any token-minting scope in its environment - Watch for the "Trinitite" IOCs: a new GitHub repository under any of your developers' accounts named
<Touhou-name>-<Touhou-name>-<number>with description exactlyTrinitite: Sponsored by Preview 2 Effectsand aresults/doubletrinnys-*.jsonfile 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 - Anyone who previously mirrored
@7nohe/openapi-react-query-codegento 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
Sources
- GHSA-rg27-qr39-ch6w - @7nohe/openapi-react-query-codegen (10 malicious versions, "Trinitite" worm)github.com
- Popular code generator for TanStack Query hit by supply chain wormaikido.dev
- Mini Shai-Hulud Strikes Again: openapi-react-query-codegensafedep.io
- @7nohe/openapi-react-query-codegen - npm registry listingnpmjs.com
- 7nohe/openapi-react-query-codegen - upstream source repositorygithub.com
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.