Mini Shai-Hulud hits openapi-react-query-codegen: 10 malicious versions, npm provenance, and why TanStack Query itself was not compromised Skip to content

Mini Shai-Hulud hits openapi-react-query-codegen: 10 malicious versions, npm provenance, and why TanStack Query itself was not compromised

Verified analysis of the August 28, 2026 attack on @7nohe/openapi-react-query-codegen: 10 malicious versions, GitHub Actions issue_comment abuse, npm Trusted Publishing, valid provenance, binding.gyp, IOCs, remediation and the distinction from TanStack Query.

Published Written by Reading time 17 min read

Verified analysis of the August 28, 2026 attack on @7nohe/openapi-react-query-codegen: 10 malicious versions, GitHub Actions issue_comment abuse, npm Trusted Publishing, valid provenance, binding.gyp, IOCs, remediation and the distinction from TanStack Query.

On this page
  1. 1TL;DR
  2. 2What happened on August 28?
  3. 3TanStack Query itself was not compromised
  4. 4What does the package do?
  5. 5How widely used was it?
  6. 6The compromise began in GitHub Actions, not npm
  7. 7One comment could enter the release path
  8. 8Checking out the fork turned input into execution
  9. 9id-token: write enabled Trusted Publishing
  10. 10No maintainer password theft was required
  11. 11Malicious releases had valid provenance
  12. 12Provenance is not malware detection
  13. 13First execution path: binding.gyp
  14. 14Second execution path: explicit preinstall
  15. 15The two prereleases were different
  16. 16Main payload: 3FWCvzduYZg.js
  17. 17What the payload did at runtime
  18. 18Which secrets should be considered exposed?
  19. 19Why a dev dependency can be extremely dangerous
  20. 20Package installation is a code-execution surface
  21. 21Was TeamPCP definitely behind it?
  22. 22Why Mini Shai-Hulud keeps appearing
  23. 23The May TanStack attack was a different technical incident
  24. 24TanStack Query was clean in May too
  25. 25The May incident demonstrated real downstream consequences
  26. 26August attack vs May attack
  27. 27How to check whether your project was affected
  28. 28Important IOCs
  29. 29What to do after an affected installation
  30. 30Which versions are safe?
  31. 31What did upstream change?
  32. 32How to harden GitHub Actions
  33. 33How to harden dependency installation
  34. 34Production checklist
  35. 35POLPROG verdict

On August 28, 2026, a new npm supply-chain compromise hit @7nohe/openapi-react-query-codegen, a code generator that produces TypeScript clients and TanStack Query hooks from OpenAPI schemas.[1][2][3]

The attacker did not need a maintainer's npm password or a stolen long-lived publish token.

The release workflow itself was the path.

The repository listened for:

issue_comment

and a pull-request comment with the exact body:

npm publish

could trigger the release path without verifying whether the commenter was a maintainer, collaborator, or completely external GitHub user.[1][2]

The workflow then:

checked out PR-controlled code
→ ran pnpm install
→ held id-token: write
→ published through npm Trusted Publishing

[1][2]

The result was especially important: 10 malicious versions were published with valid npm provenance.[1][3]

That gives us one of the clearest software-supply-chain lessons of 2026:

Provenance can correctly prove where a build came from while the build itself is malicious.

There is another correction that matters.

@tanstack/react-query itself was not compromised in this incident. The attacked package is an independent code generator that targets TanStack Query.[6][7]

It is not an official TanStack package.

Information status: August 31, 2026.

TL;DR

QuestionVerified answer
What was compromised?@7nohe/openapi-react-query-codegen
DateAugust 28, 2026
Malicious versions10
Stable malicious versions8
Malicious prereleases2
Was @tanstack/react-query compromised?No
Why is TanStack Query relevant?The package generates hooks/options for it
Main attack vectorMisconfigured GitHub Actions issue_comment release workflow
Maintainer npm password required?No
Long-lived npm publish token required?No
Publish authorityid-token: write + npm Trusted Publishing
Did malicious releases have provenance?Yes
Does provenance guarantee safe code?No
Main execution pathsbinding.gyp, plus preinstall in some versions
Main payload file3FWCvzduYZg.js
Current latest3.0.2
Is 3.0.2 known clean?Yes
Advisory severityCritical, CVSS 9.6
CVENo known CVE in the advisory as of Aug 31
ClassificationEmbedded malicious code / supply-chain compromise
Campaign familyResearchers link it to Mini Shai-Hulud-derived activity
Operator attribution certain?No
Priority responseIsolate host and rotate all reachable credentials from a clean machine

What happened on August 28?

GitHub Security Advisory GHSA-9pvf-vcx3-x239 lists 10 malicious versions published between roughly 20:00 and 20:21 UTC.[1]

Eight were stable:

0.5.4
0.5.5
1.6.3
1.6.4
2.2.1
2.2.2
3.0.3
3.0.4

Two were prereleases:

0.0.0-365d4eb738d3146583431948d3ba6e27a32556be
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab

[1][2]

The malicious latest tag pointed to 3.0.4 from approximately 20:19:29 UTC until about 22:51 UTC, when it was restored to clean 3.0.2.[1]

TanStack Query itself was not compromised

Headlines such as:

TanStack Query hacked

are inaccurate here.

@7nohe/openapi-react-query-codegen is an independent project.

It generates code for:

@tanstack/react-query

from an OpenAPI schema.[6]

That is a technology relationship, not package ownership.

The official @tanstack/react-query package remains separate, and TanStack's May postmortem also explicitly listed the Query family as unaffected by that earlier incident.[7][11]

The accurate statement is:

A third-party code generator used with TanStack Query was compromised.

What does the package do?

It generates:

  • typed API clients,
  • query keys,
  • queryOptions,
  • infiniteQueryOptions,
  • useQuery,
  • useMutation,
  • suspense helpers,
  • prefetch and SSR helpers.

[6]

Typical flow:

OpenAPI schema
      ↓
openapi-react-query-codegen
      ↓
TypeScript client
      ↓
TanStack Query hooks/options

It is commonly a development dependency.

That does not make it low risk.

How widely used was it?

On August 31, npm showed roughly 155,000 weekly downloads for the scoped package.[6]

That number is dynamic and should be treated as a snapshot, not a permanent historical fact.

More important is where the package runs:

  • developer laptops,
  • CI jobs,
  • release pipelines,
  • repositories with credentials,
  • machines with GitHub and cloud tooling.

Those environments are extremely attractive to credential-stealing malware.

The compromise began in GitHub Actions, not npm

The release workflow listened for:

on:
  issue_comment:
    types: [created]

[1]

issue_comment itself is not a vulnerability.

The dangerous chain was:

external comment
+
no actor authorization gate
+
checkout PR code
+
execute PR code
+
id-token: write
+
publish

The release workflow became the privilege boundary.

One comment could enter the release path

The workflow checked whether the comment:

  • belonged to a pull request,
  • had the exact body npm publish.

[1][2]

It did not adequately verify whether the commenter was:

OWNER
MEMBER
COLLABORATOR

or otherwise trusted.

That meant an external GitHub account could prepare a fork PR and trigger the privileged path with a comment.

The bug was an authorization failure around release automation.

Checking out the fork turned input into execution

Triggering a workflow does not automatically mean attacker code runs.

The critical next step was that the pipeline checked out pull-request-controlled code and ran:

pnpm install

[2]

At that point the PR content became executable inside a privileged release job.

The security boundary is simple:

untrusted code treated as data

versus:

untrusted code executed with privileges

GitHub's security guidance repeatedly warns against executing untrusted PR content in privileged workflows.[9]

id-token: write enabled Trusted Publishing

The release job had:

permissions:
  id-token: write

[1][2]

This is a legitimate permission when using OIDC-based npm Trusted Publishing.

npm's model replaces long-lived publish tokens with short-lived workload identity issued to an approved CI workflow.[10]

That is normally safer.

The failure was not that OIDC existed.

The failure was that an untrusted user could influence code executing inside the workflow that had the OIDC privilege.

No maintainer password theft was required

StepSecurity notes that the attacker did not require:

  • a maintainer npm password,
  • a long-lived npm publish token.

[2]

The older threat model is:

steal token
→ publish package

The newer model is:

control trusted workflow execution
→ workflow receives legitimate identity
→ publish package

That moves supply-chain defense from account security into CI/CD architecture.

Malicious releases had valid provenance

Because the releases came through the genuine workflow and Trusted Publishing, the malicious versions carried valid provenance attestations.[1][3]

Provenance effectively said:

this artifact came from
this repository
through this workflow

That statement could be completely true.

The missing question was:

was the code executed by that workflow authorized and benign?

Provenance is not malware detection

Provenance can prove:

  • build origin,
  • workflow identity,
  • source association,
  • chain of custody.

It does not automatically prove:

  • source code is safe,
  • PR was authorized,
  • workflow logic was secure,
  • package contains no malicious code.

Therefore:

valid provenance
≠
safe package

npm's own Trusted Publishing documentation presents provenance as origin verification, not as a universal malware verdict.[10]

First execution path: binding.gyp

Some malicious stable releases had no obvious:

"preinstall": "..."

[1]

Instead they introduced:

binding.gyp

A package that looks like a native addon can cause npm/node-gyp processing during installation.

The malicious binding.gyp abused GYP's Python expression evaluation to reach os.system() and execute the JavaScript payload.[1][5]

For defenders, this matters because scanning only lifecycle-script fields is insufficient.

Second execution path: explicit preinstall

Later stable malicious releases also included:

"preinstall": "node 3FWCvzduYZg.js"

[1][2]

Those were:

0.5.5
1.6.4
2.2.2
3.0.4

Earlier stable releases:

0.5.4
1.6.3
2.2.1
3.0.3

used the binding.gyp path without the explicit lifecycle script.[1]

A single detection rule would therefore miss part of the malicious set.

The two prereleases were different

The two malicious 0.0.0-* prereleases contained a bad preinstall reference, but:

"files": ["dist"]

excluded the referenced payload files from the tarballs.[1]

So all 10 releases are malicious publications, but they are not identical artifacts and do not all have the same execution path.

The eight stable releases are the most important execution set.

Main payload: 3FWCvzduYZg.js

Malicious stable tarballs contained:

3FWCvzduYZg.js

at roughly 4.4 to 6.4 MB, depending on the release.[1]

StepSecurity observed that 0.5.4 jumped from about 41 KB in 0.5.3 to more than 5.6 MB.[2]

A huge package-size increase in a code generator with no legitimate reason for multi-megabyte obfuscated JavaScript is a valuable anomaly signal.

What the payload did at runtime

StepSecurity detonated affected versions in isolated GitHub-hosted runners.[2]

For 3.0.4, observed activity included:

Node starts payload
→ curl downloads Bun
→ Bun executes under /tmp/trinnyyyy-*
→ gh auth token is called
→ Git credential manager queried
→ ssh / scp checked
→ running processes enumerated
→ temporary updater.py invoked

[2]

Researchers also observed GitHub API access and probing of the Google Cloud metadata hostname.

This is credential-oriented malware.

Which secrets should be considered exposed?

Actual exposure depends on the host.

A malicious install process can potentially access what the installing user or CI runner can access:

GitHub credentials
npm credentials
SSH keys
cloud environment credentials
CI/CD secrets
source repositories
deployment credentials

This does not mean every secret was stolen on every machine.

It means that if an affected version executed, all credentials reachable from that process should be treated as potentially exposed.

Why a dev dependency can be extremely dangerous

A developer may think:

it's only codegen
it never ships to the browser

That is irrelevant to install-time malware.

The payload only needs to run during:

npm install
pnpm install
yarn install

Development dependencies often execute on the most sensitive systems in the software lifecycle.

Package installation is a code-execution surface

Package managers support lifecycle hooks such as:

preinstall
install
postinstall
prepare

Native addon flows may also run tooling like node-gyp.

So package installation is effectively:

dependency resolution
+
download
+
potential code execution

Supply-chain controls must therefore operate before or during dependency installation, not only against final application artifacts.

Was TeamPCP definitely behind it?

JFrog, Socket and other researchers connect the payload to Mini Shai-Hulud and related descendants.[3][4]

But operator attribution is less certain.

Similar code and campaign markers may indicate:

  • the same group,
  • leftover access,
  • public malware reuse,
  • a copycat.

JFrog explicitly discusses that uncertainty.[4]

We should therefore distinguish:

malware family similarity

from:

proven actor identity

Why Mini Shai-Hulud keeps appearing

Mini Shai-Hulud-style campaigns focus on:

  • credential theft,
  • CI/CD systems,
  • package registries,
  • GitHub,
  • self-propagation.

In May 2026, researchers tracked waves involving TanStack, Mistral, UiPath and other ecosystems.[12]

The recurring pattern is:

enter through build/release tooling
→ obtain publish authority
→ ship trusted-looking package
→ execute on developer/CI hosts
→ steal credentials
→ propagate

The campaign name is less important than this repeatable attack model.

The May TanStack attack was a different technical incident

On May 11, 2026, the affected TanStack repository was Router/Start.[11]

The attacker chained:

  1. a pull_request_target pwn-request pattern,
  2. GitHub Actions cache poisoning,
  3. OIDC token extraction from runner memory.

The result:

42 packages
84 malicious versions

[11]

That is not the same root cause as the August 28 compromise.

TanStack Query was clean in May too

TanStack's official postmortem said only Router/Start was affected and explicitly listed Query among unaffected repositories/families.[11]

So in 2026 there were at least two incidents that can be lazily described as “TanStack-related supply-chain attacks”, yet neither justifies saying:

@tanstack/react-query was infected

May affected Router/Start.

August affected an independent code generator for TanStack Query.

The May incident demonstrated real downstream consequences

OpenAI disclosed that two employee devices were affected by the May TanStack/Mini Shai-Hulud incident.[13]

OpenAI reported:

  • credential-focused activity,
  • limited credential material exfiltrated from a subset of source repositories,
  • no evidence of user-data access,
  • no evidence of production-system or IP compromise,
  • credential and signing-certificate rotation as precautionary response.

[13]

That history explains why a short malicious-package exposure window can still matter to major organizations.

August attack vs May attack

May

fork PR
→ pull_request_target
→ poisoned cache
→ trusted release restores cache
→ OIDC token extracted from memory
→ publish

[11]

August

fork PR
→ public "npm publish" issue_comment
→ privileged workflow checks out PR
→ pnpm install executes attacker code
→ job already has id-token: write
→ Trusted Publishing

[1][2]

The August path is simpler.

No cache poisoning was required.

How to check whether your project was affected

Search lockfiles and historical build records for the exact affected versions.[1]

Check:

package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
SBOM
CI install logs
dependency caches

Do not only inspect the current package.json.

A floating range may have resolved to a malicious version during the incident window even though latest is clean today.

Important IOCs

Public indicators include:[1][2][5]

3FWCvzduYZg.js
binding.gyp
is_it_this_simple.js
nu.js
/tmp/trinnyyyy-*/bun
/tmp/*/updater.py

Also investigate:

  • unexpected Bun downloads during install,
  • gh auth token during package installation,
  • unusual Git credential-manager calls,
  • outbound GitHub release traffic from package installers,
  • unexpected node-gyp execution in a package that should not contain native code.

Behavioural detection is more durable than filename-only detection.

What to do after an affected installation

GitHub advisory and StepSecurity recommend treating the host as potentially compromised.[1][2]

Minimum response:

1. stop builds
2. isolate the host
3. use a separate clean machine
4. rotate all reachable credentials
5. invalidate active sessions
6. review GitHub/npm/cloud audit logs
7. purge dependency caches
8. discard artifacts built on the exposed runner
9. rebuild from clean inputs

Do not rotate only the npm token if the process could access more.

Which versions are safe?

The GitHub advisory points to 3.0.2 as known good and says releases published before August 28 are not affected by this incident.[1]

StepSecurity lists clean predecessors for each release line:

0.5.3
1.6.2
2.2.0
3.0.2

[2]

As of August 31, npm again shows:

latest = 3.0.2

[6]

What did upstream change?

According to the GitHub advisory, remediation included:[1]

  • removing the issue_comment release trigger,
  • moving releases to tag push,
  • revoking the npm trusted publisher,
  • rotating long-lived tokens,
  • restoring latest to 3.0.2,
  • removing the pre dist-tag,
  • deprecating all 10 malicious versions,
  • requesting npm removal.

A public interaction should never directly become a gateway to a production publish identity.

Snyk also classifies the compromise as Critical with CVSS 9.6, reinforcing the severity of install-time malicious-code execution.[8] TanStack's follow-up hardening after the May incident is also relevant context for cache, workflow and release-pipeline defenses.[14]

How to harden GitHub Actions

Do not execute untrusted PR code in privileged jobs

GitHub recommends separating untrusted build execution from privileged actions.[9]

Require actor authorization

Comment-driven release automation needs an explicit authorization gate.

Minimize permissions

A job that does not publish does not need:

id-token: write

Separate build and publish

Prefer:

untrusted CI
↓
artifact treated as data
↓
trusted trigger/review
↓
release

Pin third-party actions by SHA

Action tags are also part of the software supply chain.

How to harden dependency installation

There is no single magic switch.

Useful controls include:

  • lockfiles,
  • frozen installs,
  • package release cooldown/minimum age,
  • monitoring new versions,
  • package-size anomaly detection,
  • lifecycle-script policy,
  • sandboxed CI,
  • outbound network restrictions,
  • malicious-package scanning in addition to CVEs,
  • SBOM,
  • minimal credentials on runners.

npm Trusted Publishing still makes sense.[10]

But:

Trusted Publishing

must be paired with:

Trusted Workflow Design

Production checklist

Dependencies

  • Lockfile is mandatory.
  • CI rejects unexpected lockfile changes.
  • Minimum release age/cooldown is configured.
  • New dependency versions do not reach production immediately.
  • Package-size changes are monitored.
  • Install scripts are inspected.
  • Unexpected binding.gyp is flagged.
  • Malicious-package detection supplements CVE scanning.

GitHub Actions

  • Fork code never runs in privileged context.
  • issue_comment workflows have authorization gates.
  • pull_request_target is used only when necessary.
  • GITHUB_TOKEN is least privilege.
  • id-token: write exists only where required.
  • Publishing requires a trusted trigger.
  • Build and publish are separated.
  • Actions are pinned to commit SHA.
  • Comment-driven automation has a negative test for unauthorized users.
  • Release workflows never check out untrusted fork code.

npm

  • Trusted Publisher is limited to the minimum workflow set.
  • Unnecessary long-lived publish tokens are removed.
  • New publishes are monitored.
  • Unexpected releases alert immediately.
  • Provenance is verified but never treated as a malware verdict.
  • Incident runbook covers deprecation/revocation.

Runners and developer endpoints

  • CI runners are ephemeral.
  • Workspaces do not contain unnecessary secrets.
  • Cloud credentials are short-lived.
  • SSH keys have minimal scope.
  • Outbound traffic is monitored.
  • Dependency installs cannot reach the whole infrastructure.
  • Developer endpoints have runtime/EDR monitoring.
  • Hosts can be isolated quickly.

Incident response

  • Dependency incident owner is defined.
  • Lockfiles can be searched historically.
  • CI caches can be purged.
  • Sessions can be invalidated quickly.
  • Credential exposure from runners is mapped.
  • Credential rotation happens from a clean machine.
  • npm accounts are checked for unauthorized publishes.
  • GitHub audit logs are reviewed after rotation.

POLPROG verdict

The @7nohe/openapi-react-query-codegen compromise is one of the clearest 2026 examples of how software supply-chain attacks are changing.

The attacker did not need to:

hack npm
steal a maintainer password
defeat 2FA
steal a classic publish token

It was enough for the release workflow to let an untrusted user get attacker-controlled code executed inside a job that had Trusted Publishing authority.

That is the key shift.

Account security still matters.

But the modern security boundary increasingly includes:

CI/CD graph
workflow triggers
artifacts
caches
OIDC
release authorization
dependency execution

The second lesson is provenance.

Valid provenance remains valuable.

Here, however, it correctly attested the origin of a malicious build.

That is not a cryptographic failure.

It is a workflow-trust failure.

The third lesson is precision.

TanStack Query itself was not compromised.

A third-party generator used with TanStack Query was compromised.

Security reporting should not expand incident scope simply because a technology name appears in a package name or dependency graph.

As of August 31:

malicious versions: identified
advisory: published
latest: restored to 3.0.2
release workflow: changed

[1][6]

The most important question for JavaScript teams is therefore not only:

Did we use this package?

It is:

Does our own release pipeline contain a similar path from untrusted input to a job with publish authority?

If the answer is not immediately clear, audit your GitHub Actions workflows now.

Mini Shai-Hulud npm supply chain TanStack Query openapi-react-query-codegen GitHub Actions Trusted Publishing OIDC npm provenance DevSecOps

Frequently asked questions

Was TanStack Query hacked?

No. @tanstack/react-query is not one of the compromised packages in this incident.

What was compromised?

@7nohe/openapi-react-query-codegen, an independent code generator used with TanStack Query.

How many malicious versions were published?

10.

When?

August 28, 2026, with the main malicious stable releases published between roughly 20:00 and 20:21 UTC.

Which versions are malicious?

0.5.4, 0.5.5, 1.6.3, 1.6.4, 2.2.1, 2.2.2, 3.0.3, 3.0.4 and the two advisory-listed 0.0.0-* prereleases.

What is the current safe latest?

3.0.2, according to the advisory and npm status checked August 31.

Was a maintainer npm token stolen?

It was not required. The attacker abused a workflow using npm Trusted Publishing and OIDC.

What was the workflow flaw?

A public issue_comment could enter the release path without validating the commenter's authorization. The workflow checked out PR code and executed it inside a privileged publishing job.

Did malicious versions have npm provenance?

Yes.

How can malicious code have valid provenance?

Because it was published by the genuine trusted workflow. Provenance proves origin, not safety.

Can binding.gyp execute during installation?

Yes. It was abused as a hidden node-gyp execution path in this incident.

Did every version have preinstall?

No. Some stable versions used only binding.gyp; later releases also had an explicit preinstall.

What should I do after installing an affected version?

Isolate the system, stop builds, rotate reachable credentials from a separate clean machine, review audit logs and rebuild from clean inputs.

Is changing only the npm token enough?

No. GitHub, SSH, cloud and other credentials may also have been accessible.

Is TeamPCP definitely responsible?

Researchers connect the malware to Mini Shai-Hulud-derived activity, but public evidence should not be overstated into certain actor attribution for every new wave.

Is npm Trusted Publishing broken?

Not in that simple sense. It trusted the workflow it was configured to trust. The workflow itself allowed untrusted code into a privileged publishing path.

Sources and footnotes

  1. GitHub Security Advisory, GHSA-9pvf-vcx3-x239 — Malicious versions of @7nohe/openapi-react-query-codegen published via a compromised release workflow, August 28, 2026, accessed August 31, 2026.123456789101112131415161718192021222324
  2. StepSecurity, @7nohe/openapi-react-query-codegen Compromised Through an Exposed npm Publishing Workflow, August 28, 2026.12345678910111213141516
  3. Socket, OpenAPI React Query Codegen Compromised in Mini Shai-Hulud npm Supply Chain Attack, August 28, 2026.1234
  4. JFrog Security Research, Shai-Hulud Trinitite Hits @7nohe/openapi-react-query-codegen, August 30, 2026.12
  5. OSV, MAL-2026-15494 — malicious code in @7nohe/openapi-react-query-codegen, August 28, 2026.12
  6. npm, @7nohe/openapi-react-query-codegen, status checked August 31, 2026.123456
  7. npm, @tanstack/react-query, status checked August 31, 2026.12
  8. Snyk, Embedded Malicious Code affecting @7nohe/openapi-react-query-codegen, August 28, 2026.
  9. GitHub Docs, Securely using pull_request_target, accessed August 31, 2026.12
  10. npm Docs, Trusted publishing for npm packages, accessed August 31, 2026.123
  11. TanStack, Postmortem: TanStack npm supply-chain compromise, May 11, 2026, updated May 15, 2026.12345
  12. Aikido Security, Mini Shai-Hulud Is Back: npm Worm Hits over 160 Packages, including Mistral and Tanstack, May 12, 2026.
  13. OpenAI, Our response to the TanStack npm supply chain attack, May 13, 2026, later amended.12
  14. TanStack, Hardening TanStack After the npm Compromise, May 12, 2026, updated May 15, 2026.

Was this helpful?

Get new articles by email

One short email per new Learning article. No spam, unsubscribe in one click.

We only use your email to send new articles. No third-party sharing.

Back to Learning