/
← Voltar ao feed

Mini Shai-Hulud toolkit hits npm: @7nohe/openapi-react-query-codegen trojanized via GitHub Actions issue_comment flaw

1 fonte(s) · 1 atualização(ões) · publicado 29/08/2026 03:00 · coletado há 2 dias

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-365d4eb738d3146583431948d3ba6e27a32556be and 0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab). The canaries passed WORKFLOW_ID, REPO_ID_SUFFIX and TARGET_PACKAGES variables and were dry runs of the OIDC publishing exploit.
  • Wave 1 (20:00-20:02 UTC): Used only the binding.gyp trigger.
  • Wave 2 (20:19-20:21 UTC): Added an explicit preinstall: node 3FWCvzduYZg.js hook, 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, preinstall hook: package.json runs node 3FWCvzduYZg.js directly (Wave 2 only).
  • Loader: 3FWCvzduYZg.js is 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 a trinnyyyy-* temp directory, runs chmod 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: write permission.
  • Scope: Only this package was affected. Other @7nohe packages show no suspicious publishes, and the unscoped openapi-react-query-codegen (omridevk) is unrelated.
  • IOCs: 3FWCvzduYZg.js; binding.gyp SHA256 d3246926b20a8d021ed7de0ac8e9eee1dda986088f84ba18f31cb2042a121f5d; trinnyyyy-* temp directories; preinstall string node 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, the binding.gyp hash, trinnyyyy-* temp directories and unexpected Bun downloads. Treat affected hosts and CI runners as compromised and rotate their secrets.
  • Do not rely on --ignore-scripts alone, since binding.gyp still executes through node-gyp.
  • Harden GitHub Actions: remove untrusted issue_comment triggers or gate them on author association, avoid checking out PR head code in privileged jobs, minimize id-token: write, use persist-credentials: false and --frozen-lockfile. The maintainer's fix commit applied these changes.

Linha do tempo

  1. safedep.io ↗ · pub. 29/08/2026 03:00 · coletado 19/10 18:03 primeiro registro

    Mini Shai-Hulud toolkit hits npm: @7nohe/openapi-react-query-codegen trojanized via GitHub Actions issue_comment flaw

    ler a análise desta fonte

    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.

    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-365d4eb738d3146583431948d3ba6e27a32556be and 0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab). The canaries passed WORKFLOW_ID, REPO_ID_SUFFIX and TARGET_PACKAGES variables and were dry runs of the OIDC publishing exploit.
    • Wave 1 (20:00-20:02 UTC): Used only the binding.gyp trigger.
    • Wave 2 (20:19-20:21 UTC): Added an explicit preinstall: node 3FWCvzduYZg.js hook, 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, preinstall hook: package.json runs node 3FWCvzduYZg.js directly (Wave 2 only).
    • Loader: 3FWCvzduYZg.js is 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 a trinnyyyy-* temp directory, runs chmod 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: write permission.
    • Scope: Only this package was affected. Other @7nohe packages show no suspicious publishes, and the unscoped openapi-react-query-codegen (omridevk) is unrelated.
    • IOCs: 3FWCvzduYZg.js; binding.gyp SHA256 d3246926b20a8d021ed7de0ac8e9eee1dda986088f84ba18f31cb2042a121f5d; trinnyyyy-* temp directories; preinstall string node 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, the binding.gyp hash, trinnyyyy-* temp directories and unexpected Bun downloads. Treat affected hosts and CI runners as compromised and rotate their secrets.
    • Do not rely on --ignore-scripts alone, since binding.gyp still executes through node-gyp.
    • Harden GitHub Actions: remove untrusted issue_comment triggers or gate them on author association, avoid checking out PR head code in privileged jobs, minimize id-token: write, use persist-credentials: false and --frozen-lockfile. The maintainer's fix commit applied these changes.