Threat reportSupply ChainTL-2026-2193
npm Supply-Chain Compromise: @7nohe/openapi-react-query-codegen Ships "Trinitite" Credential-Harvesting Worm
All ten maintained release lines of @7nohe/openapi-react-query-codegen (~150,000 weekly downloads) were published with a 5.6MB obfuscated JavaScript loader after attackers abused a comment-triggered, OIDC-backed npm publish workflow that failed to verify the commenter's repository association. The malware, self-branded "Trinitite," harvests cloud/registry/CI/AI-agent credentials, poisons npm/PyPI/RubyGems/JFrog, propagates over SSH, and persists via LaunchAgents/systemd, exfiltrating encrypted data through attacker-controlled GitHub repositories.
Key facts for TeamPCP OpenAPI React Query worm
Detection coverage for TeamPCP OpenAPI React Query worm
As of 2026-11-01, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-2193 across Splunk SPL, Microsoft KQL and Sigma, covering 45 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.
Free detection: Trinitite Persistence and Cloud/Process Credential Harvesting — SPL
Detects post-exploitation Trinitite activity: creation of the macOS LaunchAgent (com.user.sysvinit-detect-fash.plist) or Linux systemd user service (sysvinit-detect-fash.service) persistence artifacts, and the credential-harvesting behaviors that follow — AWS IMDSv2/Azure/GCP instance-metadata probing, HashiCorp Vault token access, and /proc/<pid>/mem process-memory scraping used to steal cloud, registry, and AI-agent credentials.
- Languages: Splunk SPL, Microsoft KQL, Sigma
- ATT&CK: T1543.001, T1543.002, T1552.005, T1003.007, T1552.001, T1528
- Data sources: osquery file_events, auditd (Linux EXECVE), cloud instance-metadata proxy/network logs, EDR process telemetry
- Severity: critical
- Confidence: high
Splunk SPL
index=endpoint (sourcetype="osquery_result" OR sourcetype="auditd")
( (sourcetype="osquery_result" name="file_events" (target_path="*Library/LaunchAgents/com.user.sysvinit-detect-fash.plist*" OR target_path="*.config/systemd/user/sysvinit-detect-fash.service*" OR target_path="*.local/bin/sysvinit-detect-fash.sh*" OR target_path="*.config/sysvinit-detect-fash*")) OR
(sourcetype="auditd" type=EXECVE (exe="*/curl" OR exe="*/wget") (proctitle="*169.254.169.254*" OR proctitle="*metadata.google.internal*" OR proctitle="*login.microsoftonline.com*" OR proctitle="*vault*token*")) OR
(sourcetype="auditd" type=EXECVE (proctitle="*/proc/*/mem*" OR proctitle="*process_vm_readv*")) )
| eval stage=case(match(target_path,"sysvinit-detect-fash"),"persistence_artifact", match(proctitle,"169\.254\.169\.254|metadata\.google\.internal|microsoftonline|vault"),"cloud_credential_probe", match(proctitle,"/proc/.*/mem|process_vm_readv"),"proc_mem_scrape")
| table _time, host, uid, target_path, exe, proctitle, stage
| sort -_timeMicrosoft KQL
DeviceFileEvents
| where Timestamp > ago(24h)
| where FolderPath has_any (@"Library/LaunchAgents/com.user.sysvinit-detect-fash.plist", @".config/systemd/user/sysvinit-detect-fash.service", @".local/bin/sysvinit-detect-fash.sh", @".config/sysvinit-detect-fash")
| project Timestamp, DeviceName, FileName, FolderPath, InitiatingProcessFileName, Stage = "persistence_artifact"
| union (
DeviceNetworkEvents
| where Timestamp > ago(24h)
| where RemoteIP == "169.254.169.254" or RemoteUrl has_any ("metadata.google.internal","login.microsoftonline.com")
| project Timestamp, DeviceName, RemoteIP, RemoteUrl, InitiatingProcessFileName, Stage = "cloud_credential_probe"
)
| union (
DeviceProcessEvents
| where Timestamp > ago(24h)
| where ProcessCommandLine has "/proc/" and ProcessCommandLine has "/mem"
| project Timestamp, DeviceName, AccountName = InitiatingProcessAccountName, FileName, ProcessCommandLine, Stage = "proc_mem_scrape"
)
| order by Timestamp descSigma
title: Trinitite Persistence and Cloud/Process Credential Harvesting
id: 9e1a2f4c-6b3d-4a7e-8c2f-1d5e9a7b3c02
status: experimental
description: Detects creation of the Trinitite malware's macOS LaunchAgent / Linux systemd persistence artifacts (sysvinit-detect-fash family) and the follow-on cloud-metadata credential harvesting and /proc/<pid>/mem process-memory scraping used to steal AWS/Azure/GCP/Vault and AI-agent credentials.
references:
- https://socket.dev/blog/openapi-react-query-codegen-npm-compromise
author: AII-Detector — ThreadLinqs Intelligence
date: 2026-08-28
tags:
- attack.persistence
- attack.t1543.001
- attack.t1543.002
- attack.credential-access
- attack.t1552.001
- attack.t1552.005
- attack.t1003.007
- attack.t1528
logsource:
category: file_event
product: linux
detection:
selection_persistence:
TargetFilename|contains:
- 'sysvinit-detect-fash.plist'
- 'sysvinit-detect-fash.service'
- 'sysvinit-detect-fash.sh'
- 'com.user.sysvinit-detect-fash'
selection_metadata_probe:
CommandLine|contains:
- '169.254.169.254'
- 'metadata.google.internal'
selection_proc_mem:
CommandLine|contains: '/proc/'
CommandLine|contains|all:
- '/proc/'
- '/mem'
condition: 1 of selection_*
falsepositives:
- Legitimate LaunchAgents/systemd units with coincidentally similar naming from unrelated internal tooling (unlikely given the fixed artifact name)
- Legitimate cloud-native application code retrieving instance metadata for normal credential/token retrieval
level: criticalKnown false positives:
- Legitimate LaunchAgents/systemd services with coincidentally similar 'sysvinit' naming from unrelated internal tooling
- Legitimate cloud-native application code fetching instance metadata via IMDSv2 for normal credential retrieval — tune out known service accounts/hosts
Tuning notes: Baseline known-good LaunchAgent/systemd unit names per fleet and alert only on exact match to the sysvinit-detect-fash artifact family; for the cloud-metadata leg, exclude known application service accounts and instead prioritize metadata calls originating from node/npm/python child processes spawned during a package install to cut noise.
- Trinitite npm Loader Execution via Weaponized [indicator] — KQL · unlock with TL Creds
- Trinitite Persistence and Cloud/Process Credential Harvesting — KQL · unlock with TL Creds
- Trinitite GitHub Dead-Drop C2 and SSH Worm Propagation — KQL · unlock with TL Creds
- Trinitite npm Loader Execution via Weaponized [indicator] — Sigma · unlock with TL Creds
- Trinitite Persistence and Cloud/Process Credential Harvesting — Sigma · unlock with TL Creds
- Trinitite GitHub Dead-Drop C2 and SSH Worm Propagation — Sigma · unlock with TL Creds
- Trinitite npm Loader Execution via Weaponized [indicator] — SPL · unlock with TL Creds
- Trinitite GitHub Dead-Drop C2 and SSH Worm Propagation — SPL · unlock with TL Creds
Indicators of compromise for TeamPCP OpenAPI React Query worm
As of 2026-11-01, Threadlinqs Intelligence tracks 45 indicators of compromise for TL-2026-2193.
Sample indicators (3 of 45)
- Domain:
release-assets[.]githubusercontent[.]com - URL:
hxxps://registry[.]npmjs[.]org/-/npm/v1/tokens - File hash:
b49afb7dba04cd99b357ce7c652c823a3707f28e130bd5c6645851a7adc030d6
Defanged, TLP:CLEAR. Full set of 45 indicators: unlock with TL Creds.
How TeamPCP OpenAPI React Query worm works
On 2026-08-28, Socket's Threat Research Team disclosed that @7nohe/openapi-react-query-codegen, a widely used React Query/TanStack Query code generator, had all ten of its maintained release lines (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 0.0.0-<commit> prereleases) published in two waves roughly 20 minutes apart carrying a malicious payload. The attackers exploited a comment-triggered GitHub Actions publish workflow that gated only on the literal text "npm publish" without verifying the commenter's repository association, allowing an untrusted GitHub account to publish contents from a fork (github.com/p00paboot/openapi-react-query-codegen) under the legitimate repository's OIDC trusted-publishing identity. Because the resulting npm provenance attestations record the clean v3.0.2 commit on refs/heads/main, the malicious releases carry valid provenance and defeat `npm audit signatures` as a standalone control.
Execution is triggered without a conventional preinstall/postinstall script in most versions: an obfuscated `binding.gyp` uses Python object/class-hierarchy traversal to reach `os.system()` during node-gyp's native-build step, launching a single-byte-XOR-obfuscated ~5.7MB JavaScript file (`3FWCvzduYZg.js`). A later wave adds a direct `"preinstall": "node 3FWCvzduYZg.js"` trigger, and prerelease builds use alternate loaders (`is_it_this_simple.js`, `nu.js`) via a Bun-based installer path. At runtime the loader decrypts an embedded AES-128-GCM payload to a randomly named temp file, executes it with `child_process.execSync`, and deletes it immediately after.
The payload, which self-identifies in strings as "Trinitite: Sponsored by Preview 2 Effects," systematically harvests AWS (IMDSv2/instance-role/web-identity tokens), Azure (Microsoft Graph tenant/object/client data), GCP metadata/service-account tokens, and HashiCorp Vault secrets; validates and steals npm, PyPI, RubyGems, and JFrog Artifactory tokens; scrapes GitHub tokens and Actions secrets; and targets AI coding-agent configuration for Claude, GitHub Copilot, Cursor, Cline, and Aider. Discovery uses filesystem scanning of up to 12,000 files, `/proc/<pid>/mem` process-memory scraping on Linux, environment-variable enumeration, and cloud metadata probing. Confirmed secrets are used to poison other packages the victim can write to: npm/JFrog tarballs are modified and republished; owned RubyGems are downloaded, re-packed, and resubmitted; and PyPI typosquats are generated (up to 20 suffix variants such as `-mcp`/`-mpc`) and uploaded when the payload's `TYPO_MODE` flag is set. Where GitHub push access exists, the malware injects `.github/_index.js` and a deployment-triggered workflow named "ClaudeCode Review" that serializes repository secrets into an exfiltrated artifact, and separately propagates laterally over noninteractive SSH (`StrictHostKeyChecking=no`, `PasswordAuthentication=no`), SCP-ing `ai_setup.sh`/`ai_init.js` to reachable hosts and executing the implant remotely.
Host persistence is established via a macOS LaunchAgent (`~/Library/LaunchAgents/com.user.sysvinit-detect-fash.plist`, RunAtLoad/KeepAlive) or a Linux systemd user service with lingering enabled (`~/.config/systemd/user/sysvinit-detect-fash.service`), plus injected hook commands in VS Code/Cursor/Aider configuration that re-trigger the payload at session start. Collected data is chunked at 102,400 bytes, gzip-compressed, and encrypted with AES-256-GCM under an RSA-OAEP-wrapped key before being committed to newly created, randomly Touhou-themed public GitHub repositories for exfiltration. A separate command channel polls GitHub commit search hourly for the query `firedalazer`, parsing messages formatted `n1ggatr1n <base64-url>.<base64-signature>`, verifying them with RSA-PSS/SHA-256 against an embedded public key, and executing the resulting Python commands; a companion token-monitor polls the GitHub API once per minute for up to 259,200 seconds (72 hours) and `eval`s a stored shell handler on receiving an HTTP 4xx response.
Socket notes material behavioral overlap with Microsoft's "Mini Shai-Hulud" campaign lineage (npm delivery, obfuscated bundles, Bun loaders, credential harvesting, GitHub Actions abuse, package poisoning, GitHub-hosted exfiltration) but explicitly declines to confirm shared operators. Independent analysis from Aikido Security ties the incident's "Trinitite" branding and binding.gyp sandbox-escape technique to possible TeamPCP involvement — notable because two alleged TeamPCP members were arrested in Western Australia on 2026-08-26, two days before this compromise was published, leaving open whether this is a copycat, a surviving affiliate, or an unrelated actor. No CVE or GHSA identifier had been assigned at time of publication, and all ten malicious versions remained installable when Socket's report went live.
MITRE ATT&CK techniques by tactic:
Credential Access
T1003.007 OS Credential Dumping: Proc Filesystem; T1528 Steal Application Access Token; T1552.001 Unsecured Credentials: Credentials In Files; T1552.004 Unsecured Credentials; T1552.005 Unsecured Credentials: Cloud Instance Metadata API
Lateral Movement
T1021.004 Remote Services: SSH; T1570 Lateral Tool Transfer
Defense Evasion
T1027 Obfuscated Files or Information; T1027.013 Obfuscated Files or Information; T1070.004 Indicator Removal: File Deletion; T1140 Deobfuscate/Decode Files or Information; T1497.001 Virtualization/Sandbox Evasion
Execution
T1059.004 Command and Scripting Interpreter: Unix Shell; T1059.006 Command and Scripting Interpreter: Python; T1059.007 Command and Scripting Interpreter: JavaScript
Command and Control
T1102.002 Web Service: Bidirectional Communication; T1105 Ingress Tool Transfer; T1573.002 Encrypted Channel: Asymmetric Cryptography
Initial Access
T1195.001 Supply Chain Compromise: Compromise Software Dependencies and Development Tools; T1195.002 Supply Chain Compromise: Compromise Software Supply Chain
Discovery
T1518.001 Software Discovery; T1614.001 System Location Discovery
Persistence
T1543.001 Create or Modify System Process: Launch Agent; T1543.002 Create or Modify System Process: Systemd Service
Collection
T1560.001 Archive Collected Data: Archive via Utility
Exfiltration
T1567.001 Exfiltration Over Web Service: Exfiltration to Code Repository
Remediation for TeamPCP OpenAPI React Query worm
Patches
- No official patched release exists yet; the only current remediation is rollback to the pre-compromise versions 0.5.3, 1.6.2, 2.2.0, or 3.0.2
Immediate actions
- Pin or roll back to the last known-clean releases (0.5.3, 1.6.2, 2.2.0, 3.0.2) and purge all ten malicious versions (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 0.0.0-<commit> prereleases) from lockfiles, artifact caches, and CI runner images
- Rotate every credential reachable from any host that ran `npm install` against the affected package: npm/PyPI/RubyGems/JFrog tokens, GitHub PATs and Actions secrets, AWS/Azure/GCP instance credentials, and HashiCorp Vault tokens
- Hunt for and remove persistence artifacts: the LaunchAgent com.user.sysvinit-detect-fash.plist, the systemd user service sysvinit-detect-fash.service, ~/.local/bin/sysvinit-detect-fash.sh, and injected startup hooks in VS Code/Cursor/Aider configuration
- Audit repositories reachable by any exposed GitHub token for the injected .github/_index.js file, a workflow named "ClaudeCode Review", and any newly created public repositories with Touhou-themed names
- Check outbound network/API logs for GitHub commit-search queries containing "firedalazer" and hourly GitHub API polling patterns, which indicate an active C2 channel
Workarounds
- Block or pin @7nohe/openapi-react-query-codegen via a registry proxy/allowlist to exclude 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 both 0.0.0-<commit> prereleases
- Disable automatic node-gyp rebuild for third-party/untrusted packages in CI runners until dependency install is sandboxed
Longer-term hardening
- Require branch/reviewer-scoped approval — not a bare comment string like "npm publish" — before any comment-triggered CI/CD workflow can run with OIDC trusted-publishing credentials, and verify commenter repository association
- Sandbox npm install/build steps (disable node-gyp command-substitution execution, deny network egress during install) in both CI and developer environments
- Treat npm provenance attestations as necessary but not sufficient; pair them with behavioral/runtime scanning of install-time execution, since these releases carried fully valid provenance
Affected and fixed versions
- 7nohe (independent open-source maintainer, npm) — @7nohe/openapi-react-query-codegen
Vulnerable versions: 0.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
Fixed in: 0.5.3; 1.6.2; 2.2.0; 3.0.2
Timeline of TeamPCP OpenAPI React Query worm
Last updated · revalidated 1× · latest source
- Microsoft publishes 'Shai-Hulud 2.0' guidance covering the broader self-propagating npm worm lineage that Socket later compares this incident's behavior against.
- Microsoft Security Blog reports 'Mini Shai-Hulud,' a resurgence compromising 170+ npm packages and 2 PyPI packages via CI/CD credential theft, establishing the campaign lineage Socket flags as behaviorally similar to this incident.
- Earlier locked-ioc-44 wave compromises 32 packages under the @redhat-cloud-services npm namespace (per Phoenix Security).
- locked-ioc-44 second wave uses locked-ioc-37 execution against @vapi-ai/server-sdk, ai-sdk-ollama and ~55 other packages (per Phoenix Security / Aikido).
- Australian Federal Police, the FBI, and Western Australia Police arrest two alleged locked-ioc-43 members (aged 21 and 23) in Cottesloe and Mandurah, WA; the 23-year-old is charged with six computer-related offences tied to prior supply-chain attacks.
- Security outlets (Help Net Security, BleepingComputer, The Hacker News, CyberScoop) report the locked-ioc-43 arrests, describing over 1,000 organizations compromised, roughly 500,000 credentials stolen, and at least 300GB exfiltrated across locked-ioc-43's prior campaigns.
- Wiz reports the malicious versions were available for roughly three hours before removal.
- OSV MAL-2026-15494 (finder: Amazon Inspector) and GitHub advisory GHSA-rg27-qr39-ch6w (CWE-506) are published; Wiz incident entry created.
- Eight stable malicious versions are published between 20:00:43 and 20:20:53 UTC, plus two prerelease builds.
- GitHub user locked-ioc-41 opens PRs #215 and #216 and posts an 'npm publish' comment, triggering the vulnerable issue_comment release workflow (per StepSecurity).
- Aikido Security publishes independent corroborating analysis identifying the malware's self-branding string 'locked-ioc-42: Sponsored by Preview 2 Effects' and detailing the locked-ioc-37 Python sandbox-escape execution vector, while flagging a possible but unconfirmed locked-ioc-43 link despite the arrests two days earlier.
- Socket's Threat Research Team discovers and publicly discloses the compromise, publishing malware mechanics, credential-harvesting scope, persistence artifacts, and file-hash IOCs.
- The npm 'latest' dist-tag comes to point at compromised version 3.0.4; all ten malicious releases (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 2 prereleases) remain installable.
- Attackers exploit a comment-triggered, OIDC-backed npm publish GitHub Actions workflow on locked-ioc-21 that fails to verify commenter repository association, publishing 10 malicious version lines from a fork (locked-ioc-12) in two waves roughly 20 minutes apart.
Update history
- 2026-11-01 — locked-ioc-21 npm Package Compromised in Supply Chain Attack via GitHub Actions Workflow Abuse (locked-ioc-44 / locked-ioc-42 Worm, GHSA-rg27-qr39-ch6w): What changed No field escalations. Severity (CRITICAL), exploitability (ACTIVE) and status are already at or above the newer report's values, and the report's HIGH severity is an analyst assignment, so nothing is downgraded. The report adds
Sources cited for TeamPCP OpenAPI React Query worm
- OpenAPI React Query Codegen npm Compromise socket.dev · Vendor report · 2026-08-28
- Mini Shai-Hulud: Compromised @antv npm packages enable CI/CD credential theft Microsoft · Vendor report · 2026-05-20
- Shai-Hulud 2.0: Guidance for detecting, investigating, and defending against the supply chain attack Microsoft · Vendor report · 2025-12-09
- @7nohe/openapi-react-query-codegen on npm npmjs.com · Vendor report · 2026-08-28
- 7nohe/openapi-react-query-codegen (upstream GitHub repository) GitHub · Code repository · 2026-08-28
- Popular code generator for TanStack Query hit by supply chain worm aikido.dev · Blog · 2026-08-28
- TeamPCP arrests don't fix the supply chain risk they exposed aikido.dev · Blog · 2026-08-27
- Miasma npm Supply Chain Attack: Self-Spreading Worm via Phantom Gyp stepsecurity.io · Blog · 2026-08-28
- Two alleged TeamPCP hackers arrested over global supply chain attacks Help Net Security · News · 2026-08-27
- Australia arrests alleged TeamPCP hackers behind supply-chain attacks BleepingComputer · News · 2026-08-27
- Alleged TeamPCP Hackers Charged in Australia Over Major Supply Chain Attacks The Hacker News · News · 2026-08-27
- Two alleged TeamPCP members arrested and charged after months of software supply-chain chaos cyberscoop.com · News · 2026-08-27
- Two Arrests, One Supply-Chain Attack, and a Lot of Stolen Credentials securityaffairs.com · News · 2026-08-28
More from TeamPCP
- Developer credential exposure on dev machines: StepSecurity Dev Machine Guard credential-source inventory (context: TeamPCP stealer, Bitwarden CLI npm hijack, Shai-Hulud)
- Open Source Supply Chain Attack Surge: 56 Confirmed Attacks in 12 Months Across npm, PyPI, RubyGems, Composer, Rust Crates and GitHub Actions (Shai-Hulud, TeamPCP, Axios, Miasma, ChainDrop)
- Mini Shai-Hulud: Compromised @antv npm Packages Steal Developer and CI/CD Credentials (TeamPCP)
- Re-Enabled actions-cool GitHub Actions (issues-helper, maintain-one-comment) Resume Executing Mini Shai-Hulud CI/CD Credential-Theft Payload
- Google Cloud Threat Intelligence: Supply Chain Compromise Campaigns and Mitigation Guidance (2025-2026)
- ChainDrop/Mini Shai-Hulud npm Worm Compromises keyv, cacheable, and 400+ Downstream Packages via Ethereum-Resolved C2
Further reading
Drafted by the Threadlinqs research pipeline from 13 sources; published ; last updated .