Cross-platform detection scripts for the malicious Nx Console VS Code extension release from May 18, 2026.
This repo is a small, read-only test suite for checking the public indicators tied to the incident across macOS, Linux, and Windows. It's meant to be practical and easy to trust: no cleanup, no deletion, no "magic" side effects.
This test suite was developed to fill a gap in the community tooling available after the Nx Console incident. It was built with substantial assistance from Claude (Anthropic), with careful human review and testing on macOS, Linux, and Windows.
The goal was to create something lightweight, auditable, and genuinely useful — exactly the kind of tool I’d want to run on my own machines.
The suite focuses on the public IoCs tied to the incident:
- Extension ID:
nrwl.angular-console - Malicious version:
18.95.0 - Known files:
~/.local/share/kitty/cat.py~/Library/LaunchAgents/com.user.kitty-monitor.plist/var/tmp/.gh_update_state/tmp/kitty-*
- Known process patterns:
- Python running
cat.py - processes with
__DAEMONIZED=1in the environment when that can be inspected safely
- Python running
Use this if:
- Nx Console may have been installed on developer workstations
- you're doing a fast triage pass on a suspect host
- you want a consistent host-side check after the incident
- you need a lightweight detector before doing deeper forensics or credential rotation work
bash scripts/nx-kitty-detect-macos.shbash scripts/nx-kitty-detect-linux.shpowershell -ExecutionPolicy Bypass -File .\scripts\nx-kitty-detect-windows.ps1bash scripts/nx-kitty-detect.shThe scripts use three simple result levels:
PASS— the check came back cleanFAIL— a known IoC or very strong signal was foundWARNING— not a confirmed hit, but something worth reviewing
That keeps the output easy to scan by hand and easy to parse if you want to collect it centrally later.
A few things worth saying out loud:
- These scripts are read-only by default.
- They're safe to run multiple times.
- They do not remove files, kill processes, or change system state.
- A clean run means no known public IoCs were found by these checks. It does not guarantee the host is untouched.
If you do get a hit, treat the host as potentially compromised:
- isolate it
- preserve evidence if needed
- remove the malicious extension and persistence separately
- rotate any exposed credentials
.
├── README.md
├── .gitignore
└── scripts/
├── nx-kitty-detect.sh
├── nx-kitty-detect-macos.sh
├── nx-kitty-detect-linux.sh
└── nx-kitty-detect-windows.ps1
The macOS script checks:
- VS Code / Cursor / VS Code Insiders extension installs
- known file IoCs
- suspicious
cat.pyprocess execution - loaded LaunchAgent state
- lightweight follow-up locations worth reviewing
Process environment inspection is limited on macOS without deeper tooling, so the __DAEMONIZED=1 check is intentionally conservative there.
The Linux script checks:
- VS Code / Cursor / VS Code Insiders extension installs
- known file IoCs
- suspicious
cat.pyprocess execution __DAEMONIZED=1via/proc/*/environ- a few practical persistence locations like autostart, systemd, cron, and shell startup files
The Windows script checks the closest practical equivalents:
- VS Code / Cursor / VS Code Insiders extension installs
- suspicious
kitty-*temp artifacts - Python processes that look like
cat.py - common Run / Startup persistence spots
- suspiciously named scheduled tasks
As usual on Windows, built-in inspection of arbitrary process environment blocks is limited, so the __DAEMONIZED=1 signal is more heuristic there.
If a machine looks suspicious, follow up with a deeper review of:
- VS Code extension install timestamps
- VS Code logs and
globalStorage - GitHub CLI auth state
~/.npmrc~/.aws~/.ssh- shell history / PowerShell history
Useful places to review:
~/Library/Application Support/Code/User/globalStorage~/Library/Application Support/Code/logs
~/.config/Code/User/globalStorage~/.config/Code/logs
%APPDATA%\Code\User\globalStorage%APPDATA%\Code\logs
If you want to use this in fleet tooling, the current output is already structured enough to be useful:
- look for
FAIL - look for
nrwl.angular-console-18.95.0 - look for
cat.py - look for
__DAEMONIZED=1 - look for
kitty- - look for
gh_update_state
If you want something machine-friendlier later, it would be straightforward to add a JSON output mode.
This suite checks the published IoCs and a few practical nearby signals. It doesn't replace EDR, memory collection, or a proper incident investigation.
That's by design. The goal here is to give responders something small, readable, and dependable for the first pass.