Two weeks ago, a community member reported something alarming on my MCP marketplace: one of the skills contained a Windows trojan.
This is the post-mortem. Not the "here's what went wrong" kind — the "here's what I built so it never happens again" kind.
The incident
Skill: prospector-email-finder
Malware: Trojan:Win64/Lazy.PGPK!MTB
Vector: typosquatting GitHub repo
The attack was clever. A legitimate MCP server (prospector-mcp-email-finder) existed on GitHub. An attacker created a typosquatting copy (JuanquiFortuny/prospector-mcp-email-finder) with the same README — but with a "Download Latest Release" badge that linked to a malicious zip on raw.githubusercontent.com.
The zip contained:
Application.cmd → 'start unit.exe package.txt'
package.txt → 298 KB of obfuscated Lua bytecode
unit.exe → 872 KB PE32+ Windows executable (the trojan)
My import script downloaded the zip and committed it to dist/skills/ without scanning inside it.
What went wrong
My existing audit pipeline (Sentinel L1.5 + L1.6) only checked skill metadata — name, description, system_prompt, install command. It never looked inside the actual package zip.
That's like checking the cover of a book but never reading the pages.
What I built (8 layers, 2 weeks)
Layer 1-2: L1.5 + L1.6 (already existed)
- 6 metadata checks (auth, injection, CORS, OAuth, rate limiting)
- 18 Semgrep rules + 18 secret patterns + OSV dependency check
Layer 3: L1.7 — Binary & malware detection (NEW)
Opens the package zip (recursively — zips inside zips) and scans for:
- Windows binaries (
.exe,.dll,.scr) → instant quarantine - Launcher scripts (
.bat,.cmd,.vbs,.ps1) → instant quarantine - Nested archives (red flag — legit MCP skills don't nest zips)
- Obfuscated Lua bytecode (regex on the high-arity function signature)
- External download URLs in READMEs (the typosquatting vector)
- PowerShell
-encodedcommandpayloads -
eval(atob())obfuscation - Oversized text files >100KB that aren't valid JSON (bytecode payloads)
Layer 4: L1.8 — Malware family signatures (NEW)
17 YARA-equivalent rules for specific malware families:
- Win64/Lazy.PGPK (the one that hit us)
- Emotet, Cobalt Strike, Mimikatz, QakBot, TrickBot
- Agent Tesla, RedLine, Vidar, Raccoon, LummaC2
- AsyncRAT, njRAT, Remcos, SolarMarker, Lokibot
- DoS tools (hping3, slowloris, goldeneye)
Each rule has a MITRE ATT&CK technique ID. Any match → instant quarantine.
Layer 5: WAF — Web Application Firewall (NEW)
40 attack signatures (SQLi, XSS, SSRF, path traversal, command injection) with auto-ban after 5 hits.
Layer 6: Honeypot (NEW)
50+ fake paths (/.env, /admin, /wp-admin, /.git/config, /.aws/credentials) that auto-ban scanners for 24h and serve believable fake responses.
Layer 7: Threat Intelligence (NEW)
Real-time IOC feeds from abuse.ch (URLhaus + MalwareBazaar + ThreatFox).
Layer 8: Auto-Quarantine (NEW)
Malicious skills removed from catalog + publicly listed at /api/security?view=quarantine.
The result
Re-audited all 7,063 skills with the new layers. 0 in quarantine. The catalog was clean except for the one we already removed.
What I learned
Metadata audits are not enough. If you run a marketplace for code that agents will execute, you have to look inside the packages.
Typosquatting is the #1 threat. Attackers don't need to hack your platform — they just need to create a repo that looks similar to a legitimate one and add a "Download" button.
Transparency builds trust. Publishing the quarantine list, the audit methodology, and the incident history at
/trustdoes more for credibility than any security badge.Free tier is sufficient. The whole thing runs on Vercel Hobby ($0/month) + GitHub Actions (free). You don't need enterprise infrastructure to do security right.
The trojan's silver lining
The prospector incident was the best thing that happened to MarketNow. It forced me to build real security instead of performative security. Now every skill in the catalog is scanned by 8 layers including YARA-equivalent malware family detection — and the whole thing is verifiable by anyone.
Try it: https://marketnow.site
Security overview: https://marketnow.site/api/security
Trust page: https://marketnow.site/trust
GitHub: https://github.com/edgarfloresguerra2011-a11y/marketnow
— Edison Flores, AliceLabs LLC
Top comments (1)
This is a useful post-mortem because it separates metadata trust from artifact trust. MCP marketplaces are going to need both.
One layer I'd add to the list: provenance checks before import. For example, compare the package source against the canonical repo owner, require immutable release digests, and treat README download links as untrusted unless they point to the same verified release artifact. The typosquatting vector here is a good reminder that a convincing README is not a supply-chain control.
Also +1 on recursive archive scanning. It is boring infrastructure until the day it is the only thing between "indexed a tool" and "distributed malware".