BACK TO BLOGS Back to Press Releases

GitHub breach likely caused by Nx Console compromise

Written by:

ThreatLocker Threat Intelligence

Malicious VS code extension causes GitHub breach

On May 19th, 2026, 11:48 p.m. UTC GitHub announced on X that they were investigating unauthorized access to their internal repositories. This announcement came after they detected an employee device utilizing a malicious VS code extension that had been poisoned.  

Shortly after the public disclosure, TeamPCP announced that they will be auctioning off GitHub’s source code to the highest bidder. Minor edits to the original post have been captured, with Lapsus being authorized to broker the sale of GitHub’s data.

Figure 1: TeamPCP Data Auction
Figure 2: LAPSUS$ Group

Prior to these events, on May 18, 2026, the compromised Nx Console version 18.95.0 was published. Our analysis has uncovered a shared artifact that was found present with the recent @antv compromise that was propagating Mini Shai-Hulud.  

The malicious Nx Console extension and @antv packages created Python C2 backdoors at ~/.local/share/kitty/cat.py. With the recent disclosures, timeline of events, and incident artifacts, it appears that the GitHub compromise was a downstream effect of the malicious Nx Console packages.

Initial compromise stems from stolen GitHub credential  

The initial compromise of the Nx Console extension stems from a stolen GitHub credential belonging to an Nx developer, allowing for the publishing and distribution of the backdoored version v18.95.0 of Nx Console. The affected extension bundle included a block of minified and highly obfuscated JavaScript, main.js, which was designed to impersonate legitimate MCP server functionality and upon workspace activation would fetch a package titled “nx-next” from an orphaned commit in the official “nrwl/nx” repository.

Figure 3: main.js Injected Commands

This retrieved package JSON contained a bin entry pointing to the “index.js” file within the package, which serves as the second stage payload, also containing minified and highly obfuscated JavaScript with multiple layers.  

Figure 4: package.json

Obfuscation methods used include a shuffled string table, PBKDF2-runtime string decryption, mangled and split identifiers, and encrypted blobs of additional data. To prevent detonation in analysis environments, the script additionally queries host CPU count and checks for a generated lock file within a temporary directory. Geolocation checks based on time zone and locale are invoked to avoid execution in CIS countries, including Russia.

Figure 5: Encrypted Strings

For persistence, a kitty-monitor daemon is installed along with ~/.local/share/kitty/cat.py to provide a C2 backdoor into the environment. Previous attacks have depended on this daemon to query GitHub APIs for tokens belonging to dead drop repositories and trigger a deadman switch if that token returns as invalid. This C2 framework can also accept commands by querying the keyword “firedalazer”, executing commands that are found in recent commits and validate against embedded keys.  

Figure 6: cat.py C2 Installation

Several secrets and credentials are then searched for to extract and exfiltrate including PyPi, NPM, Bitwarden, 1Password (OP), AWS, and many others. AWS tokens and secrets are captured by querying the APIPA address “169.254.169.254”, which is used to host local AWS IMDS instances.

Figure 7: Captured Tokens and Secrets

Figure 8: AWS IMDS Instance

The /proc path on linux allows for processes to query process information which includes process memory and its contents. The Github Actions Runner.Worker process has been known to store tokens, credentials, and other plaintext secrets in memory. The findRunnerWorkerPIDLinux function appears to find and query this process for any valuable data to extract and exfiltrate.  

Figure 9: Github Runner.Worker Process

As seen by previous implementations of Mini Shai Hulud, functionality is added at the end of the script to delete the home ~/ and ~/Documents folders of the victim if the dead drop repositories are deleted before persistence is removed.

Figure 10: Delete Home and Documents

Mitigations

TeamPCP targets developer credentials by deploying info-stealing malware through compromised supply chains. By following best practices for cloud and web application, security organizations can mitigate the risk(s) posed by these threat actors:  

  • Proper credential management and storage, ensuring that credentials are not saved as clear text.
  • Service accounts should be configured to require MFA and not just an API key.  
  • Enforce IMDSV2 on all AWS services and allowlisting from approved S3 resources.
  • Implement authentication with least privilege principles to Docker and Kubernetes services.

IOCs

Malicious Extension and Package Indicators

  • nrwl.angular-console
  • Malicious version 18.95.0
  • nxConsole.mcpExtensionInstalledSha
  • VS Code globalState value
  • 558b09d7ad0d1660e2a0fb8a06da81a6f42e06d2
  • github:nrwl/nx#558b09d7

File Hashes

  • Malicious VSIX, Nx Console v18.95.0
  • SHA-256: 1a4afce34918bdc74ae3f31edaffffaa0ee074d83618f53edfd88137927340b8
  • Malicious main.js inside VSIX
  • SHA-256: b0cefb66b953e5184b6adb3035e9e267335ac5eabfe1848e07834777b9397b74
  • Obfuscated payload index.js from orphan commit
  • SHA-256: e7347d90653efc565f03733a95e9209d78f9cfa81e31ff2b2dd9d48d75a4b8b1
  • Dropper package.json
  • SHA-256: 43f2b001846c4966073ebffa5be8f15e491a1e7d32bbd805d57406ff540e0dd9

Git Object Hashes

  • Malicious orphan commit
  • SHA: 558b09d7ad0d1660e2a0fb8a06da81a6f42e06d2
  • Commit tree
  • SHA: ba642fe2c7c65e42dd7f6444b83023dc6827e08c
  • index.js blob
  • SHA: acfc3f957a63b4cde93ff645f2b6bf26a8ed1bbf
  • package.json blob
  • SHA: 9d88f040c44b5f4d5f9db15ff89310776c168e99

Persistence and Filesystem Artifacts

  • ~/.local/share/kitty/cat.py
  • ~/Library/LaunchAgents/com.user.kitty-monitor.plist
  • /var/tmp/.gh_update_state
  • /tmp/kitty-*
  • path containing nrwl.angular-console-18.95.0
  • entries referencing github:nrwl/nx#558b09d7

Process Indicators

  • python or python3 process running cat.py
  • Any process with environment variable __DAEMONIZED=1
  • bun, node, or related process executing from /tmp/kitty-*
  • VS Code-spawned process executing GitHub/Nx payload logic

Network Indicators

  • api.github.com/search/commits?q=firedalazer
  • api.github.com/search/commits?q=firedalazer&sort=committer-date&order=desc&per_page=1
  • bun.sh/install
  • DNS tunneling queries
  • Unexpected outbound HTTPS traffic on port 443 from developer machines
  • Encrypted C2 over port 443
  • 169.254.169.254 (AWS IMDS instance)
  • 169.254.170.2 (AWS ECS instance)
  • 127.0.0.1:8200
  • fulcio[.]sigstore[.]dev
  • rekor[.]sigstore[.]dev
No items found.

Start your path to stronger defenses

Start your trial

Try ThreatLocker free for 30 days and experience full Zero Trust protection in your own environment.

Book a demo

Schedule a customized demo and explore how ThreatLocker aligns with your security goals.

Ask an expert

Just starting to explore our platform? Find out what ThreatLocker is, how it works, and how it’s different.