Back to Blog

@7nohe/openapi-react-query-codegen Compromised Through an Exposed npm Publishing Workflow

An external GitHub user exploited an exposed npm publishing workflow for @7nohe/openapi-react-query-codegen and shipped ten malicious versions that run attacker code during installation.
Varun Sharma
View LinkedIn

August 28, 2026

Share on X
Share on X
Share on LinkedIn
Share on Facebook
Follow our RSS feed
openapi-react-query-codegen compromised through an exposed npm publishing workflow
Table of Contents

On August 28, 2026, an external GitHub user exploited the release workflow for @7nohe/openapi-react-query-codegen and published ten malicious npm versions. The affected releases execute attacker supplied code during installation. The eight stable releases used a malicious binding.gyp path, an explicit preinstall hook, or both. Direct execution of the payload from version 3.0.4 attempted to retrieve GitHub credentials, contacted the GitHub API, and probed the Google Cloud metadata hostname.

The attacker did not need a maintainer npm password or a long lived npm token. The repository accepted an npm publish comment from any pull request participant, checked out that pull request, installed its dependencies, and published packages with a GitHub Actions OIDC identity.

StepSecurity reproduced the installation behavior on isolated GitHub hosted runners under Harden-Runner.

Action required: Do not install @7nohe/openapi-react-query-codegen@latest. At the time of publication, npm still mapped latest to malicious version 3.0.4 and had not deprecated it. If an affected version ran installation scripts, isolate the system and rotate accessible credentials from a separate clean machine.

npm current tags showing malicious version 3.0.4 as latest
npm still mapped the latest tag to malicious version 3.0.4 when this screenshot was captured.

The Compromised Package

PackageAffected versionsWhy flagged
@7nohe/openapi-react-query-codegen0.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-ec7876d6c917dad516ba69bbfafc948b834bf0abAttacker controlled install hooks, large obfuscated payloads in the stable releases, Bun downloads during installation, and no matching reviewed source release

The eight malicious stable versions appeared between 20:00:43 and 20:20:53 UTC. Version 0.5.4 grew from 41,621 bytes in 0.5.3 to 5,658,449 bytes. The other malicious stable artifacts ranged from 4.46 MB to 6.53 MB. Version 3.0.4 added this lifecycle hook:

npm version history showing the malicious release sequence
The npm version history exposed three additional malicious stable releases: 0.5.5, 1.6.4, and 2.2.2.
"preinstall": "node 3FWCvzduYZg.js"

The 3FWCvzduYZg.js file is 6,384,601 bytes. Its SHA256 digest is:

b24d121667f21f492cb9db34fbfd515d5922a8dd30b9c45215c7220abbb10ca8
npm package file list showing the 6.38 MB JavaScript payload and binding.gyp
The published 3.0.4 artifact contains the 6.38 MB payload and the malicious binding.gyp file.

StepSecurity OSS AI Package Analyst assigned version 3.0.4 a security score of 0, marked its risk as critical, and returned a rejected recommendation. That hosted model identified XOR decoded code passed to the JavaScript Function constructor, the malicious preinstall hook, and an obfuscated binding.gyp execution path. This verdict is independent static analysis. The runner observations below are direct behavioral evidence.

StepSecurity OSS AI Package Analyst critical verdict
StepSecurity OSS AI Package Analyst returned a critical risk score of 0 and rejected the package.

How the Attack Works

An external comment reached a trusted publisher

The repository release workflow listened for issue_comment events. It required only that the comment belonged to a pull request and that its body exactly matched npm publish. The workflow did not verify the commenter's repository role or association.

GitHub Actions release workflow showing issue comment trigger and id token permission
The release workflow granted id-token: write and accepted the npm publish pull request comment without checking the actor's authorization.

The workflow then checked out the pull request head, ran pnpm install, and published through npm Trusted Publishing with id-token: write. This placed untrusted pull request code inside a privileged release job.

GitHub Actions workflow checking out a pull request and installing its dependencies
The privileged workflow checked out attacker controlled pull request code and ran pnpm install.
GitHub Actions workflow publishing the pull request artifact to npm
The issue comment path then published the generated prerelease through npm Trusted Publishing.

GitHub user p00paboot opened pull requests #215 and #216, then posted the trigger comment. The related workflow runs successfully reached their publish steps. npm registry timestamps followed within seconds.

npm provenance identifying GitHub Actions and the release workflow
npm provenance ties the published package to GitHub Actions and the repository's release.yml workflow.

The stable releases execute during installation

The four stable versions detonated so far, 1.6.3, 2.2.1, 3.0.3, and 3.0.4, all caused curl to contact GitHub and release-assets.githubusercontent.com during installation. Harden-Runner then observed an executable named bun under a temporary directory with the prefix /tmp/trinnyyyy-. Registry metadata confirms that newly identified versions 0.5.5, 1.6.4, and 2.2.2 contain the same preinstall command. Version 0.5.4 was published in the same attacker controlled run and expanded by more than 5.6 MB.

Version 3.0.4 also contains a malicious binding.gyp condition. The condition traverses Python objects to reach os.system() and decodes to this command:

node 3FWCvzduYZg.js

This gives the attacker another path to the same payload when node-gyp evaluates the file.

Runtime Validation with StepSecurity Harden-Runner

The Harden-Runner analysis run tested every affected version at installation time and import time. It also executed the 3.0.4 payload directly inside the GitHub hosted runner with CI marker variables removed.

The direct payload job produced this sequence:

  1. Node executed 3FWCvzduYZg.js.
  2. The payload spawned curl and downloaded Bun from GitHub release infrastructure.
  3. The new executable ran from /tmp/trinnyyyy-doj0LR/bun.
  4. The staged Bun code ran gh auth token.
  5. It ran git credential-manager github list --no-ui.
  6. It checked for ssh and scp, enumerated running processes, and invoked a shell with a temporary updater.py path.
Harden-Runner process events showing npm install spawning the payload, the Bun download, and the staged Bun execution
Harden-Runner process events capture npm install spawning the payload, the Bun download, and the staged Bun execution.

The job specific network view ties the observed destinations to the payload processes.

Indicators of Compromise

Package versions

@7nohe/openapi-react-query-codegen@0.5.4
@7nohe/openapi-react-query-codegen@0.5.5
@7nohe/openapi-react-query-codegen@1.6.3
@7nohe/openapi-react-query-codegen@1.6.4
@7nohe/openapi-react-query-codegen@2.2.1
@7nohe/openapi-react-query-codegen@2.2.2
@7nohe/openapi-react-query-codegen@3.0.3
@7nohe/openapi-react-query-codegen@3.0.4
@7nohe/openapi-react-query-codegen@0.0.0-365d4eb738d3146583431948d3ba6e27a32556be
@7nohe/openapi-react-query-codegen@0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab

Files and artifacts

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

Registry hashes

Versionnpm tarball SHA1
0.5.42d934cf137a4e62519f88e7ab669d2fabda33867
0.5.5337ae261e4e73a9f365f892dcef2dc6f6932e90a
1.6.30f9bc76952b67d7a28a57d1e726293f417df0119
1.6.46499c9ab4e60f9b1db6756cb0de55ebc334a72d1
2.2.15ab130e4736d4582899af2385ec7eb5a33619d05
2.2.2fc60551b23485829c0a6e910224b049c891a49b8
0.0.0-365d4eb738d3146583431948d3ba6e27a32556bee7a07ca4a3cd51c262495f473abe4c4e505b7be4
3.0.3bafa4edaa6812fce10ae703ae450cc88ebbe1730
3.0.43fc635b988db2bd647b8578dfc1a85769913b708
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab206b18c418434abc994bd40e021edcc334eee89b

Am I Affected?

CI/CD pipelines

Search workflow logs, dependency caches, lockfiles, SBOMs, and build provenance for the affected versions. Review your Harden-Runner organization baseline for new Bun execution and unexpected GitHub API traffic during dependency installation.

Developer machines

Search developer workstations for the payload filename, the temporary trinnyyyy directories, and unexpected Bun executables created at the time of installation. Dev Machine Guard suspicious file rules can help detect these artifacts across managed developer endpoints.

Recovery Steps

  1. Stop builds and isolate systems that installed an affected version with lifecycle scripts enabled.
  2. Use a separate clean system to rotate npm, GitHub, cloud, CI/CD, SSH, signing, and deployment credentials that the affected process could access.
  3. Invalidate active sessions and review audit logs for unusual repository access, package publication, cloud API calls, or newly created credentials.
  4. Remove affected dependency caches and discard artifacts built on exposed runners.
  5. Pin the appropriate release line to known clean version 0.5.3, 1.6.2, 2.2.0, or 3.0.2.
  6. Rebuild from a clean environment with a reviewed lockfile.

How StepSecurity Protects Against This

Harden-Runner records process and network activity in GitHub Actions. Its runtime evidence exposed the Bun download and the temporary executable in this incident. In block mode, Harden-Runner permits only endpoints on the job's configured allowlist.

Interactive demo: a deep dive into Harden-Runner detecting and blocking CI/CD compromise at runtime.

Dev Machine Guard extends compromised package detection to developer workstations, where npm lifecycle malware can access long lived credentials and local source code. Suspicious file rules can identify the payload name and temporary executable pattern associated with this incident.

Interactive demo: how Dev Machine Guard and Secure Registry protect developer machines and keep malicious packages out.

Acknowledgment

Charlie Eriksen reported the malicious releases in GitHub issue #217.

References

Check whether this package is in your environment

StepSecurity checks repositories, CI/CD pipelines, and developer machines for compromised packages.

Explore Related Posts