Mini Shai-Hulud toolkit hits npm: @7nohe/openapi-react-query-codegen trojanized via GitHub Actions issue_comment flaw
On August 28, 2026, an attacker published 10 malicious versions of the npm package @7nohe/openapi-react-query-codegen (about 671K downloads/month) without stealing any credentials. They abused the repository's GitHub Actions release.yml workflow, which had an issue_comment trigger with no author-association gate. Commenting npm publish on a fork pull request made the workflow check out attacker code, run pnpm install and execute the attacker's preinstall hook inside a job holding id-token: write, which allowed minting npm OIDC trusted-publishing tokens. The payload's Bun download pattern, trinnyyyy- temp directory and obfuscation style match the Mini Shai-Hulud toolkit seen in the SAP (April 2026) and AntV (May 2026) compromises. All malicious versions have been removed from npm, and the last safe version is 3.0.2. The final objective of the payload (credential theft, backdoor, or both) has not yet been established.
Detalhes técnicos
- Publishing window: All versions were published on 2026-08-28 between 20:00 and 20:21 UTC, in two waves plus two canary test versions (
0.0.0-365d4eb738d3146583431948d3ba6e27a32556beand0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab). The canaries passedWORKFLOW_ID,REPO_ID_SUFFIXandTARGET_PACKAGESvariables and were dry runs of the OIDC publishing exploit. - Wave 1 (20:00-20:02 UTC): Used only the
binding.gyptrigger. - Wave 2 (20:19-20:21 UTC): Added an explicit
preinstall: node 3FWCvzduYZg.jshook, giving redundancy. It was published less than one minute after the first public security report. - Trigger 1,
binding.gyp: node-gyp evaluates Python expressions, and the file uses a Unicode-escaped class hierarchy traversal (catch_warnings->__import__('os').system('node 3FWCvzduYZg.js')). It runs even with--ignore-scripts. The SHA256 is identical across all eight payload versions. - Trigger 2,
preinstallhook:package.jsonrunsnode 3FWCvzduYZg.jsdirectly (Wave 2 only). - Loader:
3FWCvzduYZg.jsis a single-line file of 4.3-6.4 MB, unique per version. It decodes through XOR (key 229), AES-128-GCM and javascript-obfuscator layers. The bootstrapper downloads Bun v1.4.0 from GitHub releases into atrinnyyyy-*temp directory, runschmod 755, and on Windows renames the binary to a random six-character name. The 796KB layer 3b bundle has not been fully decoded. - Workflow flaws: No author-association gate, checkout of PR head code in a privileged context, and
id-token: writepermission. - Scope: Only this package was affected. Other
@7nohepackages show no suspicious publishes, and the unscopedopenapi-react-query-codegen(omridevk) is unrelated. - IOCs:
3FWCvzduYZg.js;binding.gypSHA256d3246926b20a8d021ed7de0ac8e9eee1dda986088f84ba18f31cb2042a121f5d;trinnyyyy-*temp directories; preinstall stringnode 3FWCvzduYZg.js.
Remediação
- Pin to 3.0.2 (the latest dist-tag) and audit lockfiles and CI logs for installs on 2026-08-28 that could have resolved to compromised versions. Ranges such as ^3.0.0, ^2.2.0, ^1.6.0 and ^0.5.0 were exposed.
- Hunt for
3FWCvzduYZg.js, thebinding.gyphash,trinnyyyy-*temp directories and unexpected Bun downloads. Treat affected hosts and CI runners as compromised and rotate their secrets. - Do not rely on
--ignore-scriptsalone, sincebinding.gypstill executes through node-gyp. - Harden GitHub Actions: remove untrusted
issue_commenttriggers or gate them on author association, avoid checking out PR head code in privileged jobs, minimizeid-token: write, usepersist-credentials: falseand--frozen-lockfile. The maintainer's fix commit applied these changes.
Linha do tempo
-
Mini Shai-Hulud toolkit hits npm: @7nohe/openapi-react-query-codegen trojanized via GitHub Actions issue_comment flaw
ler a análise desta fonte ocultar
On August 28, 2026, an attacker published 10 malicious versions of the npm package @7nohe/openapi-react-query-codegen (about 671K downloads/month) without stealing any credentials. They abused the repository's GitHub Actions
release.ymlworkflow, which had anissue_commenttrigger with no author-association gate. Commentingnpm publishon a fork pull request made the workflow check out attacker code, runpnpm installand execute the attacker's preinstall hook inside a job holdingid-token: write, which allowed minting npm OIDC trusted-publishing tokens. The payload's Bun download pattern,trinnyyyy-temp directory and obfuscation style match the Mini Shai-Hulud toolkit seen in the SAP (April 2026) and AntV (May 2026) compromises. All malicious versions have been removed from npm, and the last safe version is 3.0.2. The final objective of the payload (credential theft, backdoor, or both) has not yet been established.Technical Details
- Publishing window: All versions were published on 2026-08-28 between 20:00 and 20:21 UTC, in two waves plus two canary test versions (
0.0.0-365d4eb738d3146583431948d3ba6e27a32556beand0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab). The canaries passedWORKFLOW_ID,REPO_ID_SUFFIXandTARGET_PACKAGESvariables and were dry runs of the OIDC publishing exploit. - Wave 1 (20:00-20:02 UTC): Used only the
binding.gyptrigger. - Wave 2 (20:19-20:21 UTC): Added an explicit
preinstall: node 3FWCvzduYZg.jshook, giving redundancy. It was published less than one minute after the first public security report. - Trigger 1,
binding.gyp: node-gyp evaluates Python expressions, and the file uses a Unicode-escaped class hierarchy traversal (catch_warnings->__import__('os').system('node 3FWCvzduYZg.js')). It runs even with--ignore-scripts. The SHA256 is identical across all eight payload versions. - Trigger 2,
preinstallhook:package.jsonrunsnode 3FWCvzduYZg.jsdirectly (Wave 2 only). - Loader:
3FWCvzduYZg.jsis a single-line file of 4.3-6.4 MB, unique per version. It decodes through XOR (key 229), AES-128-GCM and javascript-obfuscator layers. The bootstrapper downloads Bun v1.4.0 from GitHub releases into atrinnyyyy-*temp directory, runschmod 755, and on Windows renames the binary to a random six-character name. The 796KB layer 3b bundle has not been fully decoded. - Workflow flaws: No author-association gate, checkout of PR head code in a privileged context, and
id-token: writepermission. - Scope: Only this package was affected. Other
@7nohepackages show no suspicious publishes, and the unscopedopenapi-react-query-codegen(omridevk) is unrelated. - IOCs:
3FWCvzduYZg.js;binding.gypSHA256d3246926b20a8d021ed7de0ac8e9eee1dda986088f84ba18f31cb2042a121f5d;trinnyyyy-*temp directories; preinstall stringnode 3FWCvzduYZg.js.
Remediation
- Pin to 3.0.2 (the latest dist-tag) and audit lockfiles and CI logs for installs on 2026-08-28 that could have resolved to compromised versions. Ranges such as ^3.0.0, ^2.2.0, ^1.6.0 and ^0.5.0 were exposed.
- Hunt for
3FWCvzduYZg.js, thebinding.gyphash,trinnyyyy-*temp directories and unexpected Bun downloads. Treat affected hosts and CI runners as compromised and rotate their secrets. - Do not rely on
--ignore-scriptsalone, sincebinding.gypstill executes through node-gyp. - Harden GitHub Actions: remove untrusted
issue_commenttriggers or gate them on author association, avoid checking out PR head code in privileged jobs, minimizeid-token: write, usepersist-credentials: falseand--frozen-lockfile. The maintainer's fix commit applied these changes.
- Publishing window: All versions were published on 2026-08-28 between 20:00 and 20:21 UTC, in two waves plus two canary test versions (