# 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.

- **Published:** 2026-08-28T00:00:00Z
- **Last reviewed:** 2026-11-01T16:46:00.307Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-2193
- **ID:** TL-2026-2193
- **Severity:** CRITICAL
- **Category:** SUPPLY_CHAIN
- **Status:** ACTIVE
- **Actor:** TeamPCP
- **Detections:** 9 (1 shown free below) · **IOCs:** 45 (3 shown free below)

## Description

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

- T1195.001 Supply Chain Compromise: Compromise Software Dependencies and Development Tools
- T1195.002 Supply Chain Compromise: Compromise Software Supply Chain
- T1059.007 Command and Scripting Interpreter: JavaScript
- T1059.006 Command and Scripting Interpreter: Python
- T1059.004 Command and Scripting Interpreter: Unix Shell
- T1543.001 Create or Modify System Process: Launch Agent
- T1543.002 Create or Modify System Process: Systemd Service
- T1027 Obfuscated Files or Information
- T1140 Deobfuscate/Decode Files or Information
- T1070.004 Indicator Removal: File Deletion
- T1552.001 Unsecured Credentials: Credentials In Files
- T1552.005 Unsecured Credentials: Cloud Instance Metadata API
- T1003.007 OS Credential Dumping: Proc Filesystem
- T1528 Steal Application Access Token
- T1021.004 Remote Services: SSH
- T1570 Lateral Tool Transfer
- T1560.001 Archive Collected Data: Archive via Utility
- T1102.002 Web Service: Bidirectional Communication
- T1573.002 Encrypted Channel: Asymmetric Cryptography
- T1567.001 Exfiltration Over Web Service: Exfiltration to Code Repository
- T1027.013 Obfuscated Files or Information
- T1497.001 Virtualization/Sandbox Evasion
- T1614.001 System Location Discovery
- T1518.001 Software Discovery
- T1552.004 Unsecured Credentials
- T1105 Ingress Tool Transfer

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**Trinitite Persistence and Cloud/Process Credential Harvesting — SPL** (`TL-2026-2193-SPL-002`)

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

```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 -_time
```

### Microsoft KQL

```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 desc
```

### Sigma

```yaml
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: critical
```

**Known 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.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Trinitite npm Loader Execution via Weaponized [indicator] — KQL (locked: unlock with TL Creds)
- Trinitite Persistence and Cloud/Process Credential Harvesting — KQL (locked: unlock with TL Creds)
- Trinitite GitHub Dead-Drop C2 and SSH Worm Propagation — KQL (locked: unlock with TL Creds)
- Trinitite npm Loader Execution via Weaponized [indicator] — Sigma (locked: unlock with TL Creds)
- Trinitite Persistence and Cloud/Process Credential Harvesting — Sigma (locked: unlock with TL Creds)
- Trinitite GitHub Dead-Drop C2 and SSH Worm Propagation — Sigma (locked: unlock with TL Creds)
- Trinitite npm Loader Execution via Weaponized [indicator] — SPL (locked: unlock with TL Creds)
- Trinitite GitHub Dead-Drop C2 and SSH Worm Propagation — SPL (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (3 of 45)

Defanged, TLP:CLEAR.

- Domain: `release-assets[.]githubusercontent[.]com`
- URL: `hxxps://registry[.]npmjs[.]org/-/npm/v1/tokens`
- File hash: `b49afb7dba04cd99b357ce7c652c823a3707f28e130bd5c6645851a7adc030d6`

Full set of 45 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [OpenAPI React Query Codegen npm Compromise](https://socket.dev/blog/openapi-react-query-codegen-npm-compromise)
- [Popular code generator for TanStack Query hit by supply chain worm](https://www.aikido.dev/blog/popular-code-generator-for-tanstack-query-hit-by-supply-chain-worm)
- [Mini Shai-Hulud: Compromised @antv npm packages enable CI/CD credential theft](https://www.microsoft.com/en-us/security/blog/2026/05/20/mini-shai-hulud-compromised-antv-npm-packages-enable-ci-cd-credential-theft/)
- [Shai-Hulud 2.0: Guidance for detecting, investigating, and defending against the supply chain attack](https://www.microsoft.com/en-us/security/blog/2025/12/09/shai-hulud-2-0-guidance-for-detecting-investigating-and-defending-against-the-supply-chain-attack/)
- [Two alleged TeamPCP hackers arrested over global supply chain attacks](https://www.helpnetsecurity.com/2026/08/27/alleged-teampcp-hackers-arrested-australia/)
- [Australia arrests alleged TeamPCP hackers behind supply-chain attacks](https://www.bleepingcomputer.com/news/security/australia-arrests-alleged-teampcp-hackers-behind-supply-chain-attacks/)
- [Alleged TeamPCP Hackers Charged in Australia Over Major Supply Chain Attacks](https://thehackernews.com/2026/08/alleged-teampcp-hackers-charged-in.html)
- [Two alleged TeamPCP members arrested and charged after months of software supply-chain chaos](https://cyberscoop.com/teampcp-cybercrime-arrests-supply-chain-attacks/)
- [Two Arrests, One Supply-Chain Attack, and a Lot of Stolen Credentials](https://securityaffairs.com/197929/security/two-arrests-one-supply-chain-attack-and-a-lot-of-stolen-credentials.html)
- [TeamPCP arrests don't fix the supply chain risk they exposed](https://www.aikido.dev/blog/teampcp-arrested-supply-chain)
- [Miasma npm Supply Chain Attack: Self-Spreading Worm via Phantom Gyp](https://www.stepsecurity.io/blog/binding-gyp-npm-supply-chain-attack-spreads-like-worm)
- [7nohe/openapi-react-query-codegen (upstream GitHub repository)](https://github.com/7nohe/openapi-react-query-codegen)
- [@7nohe/openapi-react-query-codegen on npm](https://www.npmjs.com/package/@7nohe/openapi-react-query-codegen)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-2193
