
SubQuery Ecosystem Compromise: Hidden Credential Theft and Backdoors
StepSecurity's investigation of @subql/common@5.8.3, a malicious npm release in the SubQuery Web3 indexing framework's monorepo, found a heavily obfuscated postinstall/import-time payload (base64+XOR+gzip inside a function constructed via Function()) that spawns a detached worker to steal credentials (.npmrc, .env, AWS, SSH, kubeconfig, Vault, cloud secrets), read GitHub Actions runner memory for CI secrets, inject a camouflaged "Run Copilot" GitHub Actions workflow to exfiltrate repo secrets, and provide a remote shell/PTY over an encrypted channel to ci-artifacts.dev. The release was published via a compromised build pipeline: a workflow modification swapped the real build output for an externally downloaded, unsigned tarball from that same C2 domain immediately before publish, and the authors provide IOCs and remediation steps (credential rotation, host isolation, domain blocking).
What it is
A supply-chain compromise of @subql/common@5.8.3, published October 5, 2026 at 11:56:29 UTC, affecting the SubQuery Web3 indexing framework's shared library. Because the package is a common dependency, the compromise propagates to any SubQuery package resolving to it — including @subql/cli@6.6.3, @subql/node-core@19.3.1, @subql/query@2.25.0, and @subql/node-ethereum@6.5.0, all of which use semver ranges (~5.8.2, ^5.8.2) that permit 5.8.3 without the parent package itself being re-released. StepSecurity's dependency review of 77 @subql packages found 19 latest versions with a path to the malicious release (16 direct, 3 indirect via @subql/node-core, including @subql/node@6.4.6, @subql/node-solana@6.3.5, @subql/node-starknet@6.1.0).
How it works
The attacker's access path: on a temporary branch sharing a common parent commit, two sibling commits were pushed under account ianhe8x (both unsigned). One replaced the publish workflow with a disguised "Red Team Canary" job that published a harmless test build under the redteam tag — a dry run of the publish path. The other, separate commit modified the real release workflow to insert a step, after the legitimate yarn build, that downloads an external tarball from ci-artifacts.dev and overwrites packages/common with it before the existing publish step runs — with no hash or signature check. This means the published npm package did not contain the repository's built source.
flowchart LR
A[Shared parent commit] --> B[Canary branch:\nfake publish workflow]
A --> C[Release branch:\nreal publish workflow]
C --> D[yarn build runs]
D --> E[New step: fetch tarball\nfrom ci-artifacts.dev]
E --> F[Overwrites packages/common\nno signature check]
F --> G[Existing Publish Common\nstep runs on tampered dir]The package's reader module gained a postinstall hook and an import-time trigger (require.main !== module) that both launch a detached worker. The worker decodes a base64/XOR/gzip blob (83,408 bytes) via Function() construction. The shipped TypeScript source map is a stub with a placeholder seed array and omits both trigger points, so reviewing the mapped source would miss the payload entirely.
Preconditions / Affected
Any install (with scripts enabled) or any require/import of @subql/common@5.8.3, directly or transitively. Version 5.8.2 was checked and does not contain the payload, though the full 5.8.2 dependency tree wasn't fully audited.
What to do
- Exclude 5.8.3 everywhere, including lockfiles and transitive paths — pinning a parent package alone doesn't pin its dependencies.
- Disabling install scripts is not sufficient: importing the package also triggers the worker.
- If 5.8.3 ran: isolate the host/runner, preserve process/network evidence, and rebuild from a trusted image rather than just uninstalling (the worker is detached and persists).
- Rotate all credentials reachable by the affected process: cloud (AWS Secrets Manager/SSM across 17 regions), GitHub tokens, npm, SSH, Kubernetes, Vault.
- Block
ci-artifacts.devand search for the IOC branch namedependabot/github_actions/format/setup-formatterand workflow file.github/workflows/codeql_analysis.yml(disguised as "Run Copilot"), plus Actions run creation/deletion events and cloud secret access logs.
Caveats
StepSecurity states these are static/attempted capabilities, not confirmed successful theft on any given host — execution depends on network access, token scopes, and local permissions. The report also notes a code defect (a literal trailing ] in one AWS env var name) that may limit one credential-harvesting path, though others remain functional. Investigation is ongoing; StepSecurity says the post will be updated.
Organisations named here
- ci-artifacts.dev
- Run Copilot
- SubQuery
Technologies named here
- StepSecurity AI Package Analyst
- @subql/common
- npm pack
- gh auth token
- GitHub Actions runners
- AWS Secrets Manager / SSM Parameter Store
- Kubernetes secrets
- Vault KV
- create-release composite action
- npm
- GitHub Actions
- Node.js
- AWS
- Vault
- Kubernetes
Techniques named here
- Malicious npm package / postinstall script
- Import-time execution trigger
- Build artifact substitution in CI/CD pipeline
- Obfuscated payload / multi-layer encoding
- Source map deception
- Detached child process execution
- Credential and secrets collection
- CI runner process memory scraping
- GitHub Actions workflow injection
- Encrypted exfiltration channel
- Remote command and shell access
- Execution evasion/anti-analysis controls
- Branch/commit structuring to obscure provenance
Threat actors named here
- ianhe8x
Related in Supply Chain


