After a real trojan slipped through my MCP marketplace last week (Trojan:Win64/Lazy.PGPK!MTB
hidden in a nested zip), I went deep on defense-in-depth. The result is 8 layers running in production at marketnow.site. Here's what each layer actually catches β with concrete examples.
The cheapest layer. Runs on every skill's metadata (name, description, system_prompt, install command).
Catches:
Access-Control-Allow-Origin: *
Doesn't catch: anything inside the actual package zip. That's why the trojan got through initially.
18 Semgrep-equivalent rules + 18 secret detection patterns + OSV dependency vulnerability check.
Catches:
sk_live_*
, GitHub ghp_*
, AWS AKIA*
)`exec(req.body)`
)`fetch(req.url)`
)`readFile(req.params.path)`
)read_file
to impersonate the official one)Doesn't catch: secrets inside code blocks in README (we strip those β false positives), process.env.X
references (variable lookups, not hardcoded).
This is the layer I built after the trojan incident. It opens the actual package zip (recursively β zips inside zips) and scans for:
.exe
, .dll
, .scr
, .msi
) β instant quarantine.bat
, .cmd
, .vbs
, .ps1
) β instant quarantinestart X.exe Y.txt
pattern β the exact prospector trojan signature)function(o,R,F,U,b,p,E,M,Z,W,...)
)raw.githubusercontent.com/.../...zip
)`-encodedcommand`
`eval(atob(...))`
Catches: the exact trojan that hit us. Verified with a smoke test that scans the original malicious zip from git history.
YARA-equivalent rules for specific malware families:
Each rule has a MITRE ATT&CK technique ID. Any match β instant quarantine.
Inspects every incoming HTTP request for attack patterns:
../
, encoded %2e%2e
, /etc/passwd
, /proc/self
, Windows pathsfile://
, gopher://
, dict://
$()
, chained ; ls
, pipe | cat
, && ||
$where
, $ne
, $gt
__proto__
, constructor.prototype
`{{ }}`
, Twig `{% %}`
, JS `${ }`
with header injection**Auto-ban** after 5 WAF hits in 10 minutes (1-hour ban).
Fake vulnerable paths that auto-ban scanners for 24 hours:
/.env
β serves a fake env file with canary tokens/admin
β serves a fake admin login form/wp-admin
β serves a fake WordPress login/.git/config
β serves a fake git config/.aws/credentials
β serves fake AWS credentials/.ssh/id_rsa
β serves a fake SSH key/phpmyadmin
β serves a fake phpMyAdmin/backup.sql
β serves a fake database dump/server-status
, /.DS_Store
, /web.config
, /Dockerfile
, etc.Any access β IP banned 24h + logged publicly at /api/security?view=honeypot
.
Real-time IOC feeds from abuse.ch: Used to check skill source URLs and file hashes. If a skill's source URL is in URLhaus, it gets quarantined.
If any layer flags a skill as critical/high:
_data/quarantine/
skills_index.json
)`/api/security?view=quarantine`
for transparencyRe-audited all 14,581 skills with the new layers.
Result: 0 skills in quarantine.
The catalog was clean β the only malicious skill (prospector-email-finder) had already been removed manually. The 8 layers now run on every new skill import and every weekly batch re-audit.
`--network none`
, `--read-only`
, `--cap-drop ALL`
)Total infrastructure cost: $0/month. The marketplace is free. The security infrastructure is the product.
npx -y marketnow-mcp
Not selling anything. Looking for feedback from people who run MCP servers in production β what would make you trust a marketplace enough to install skills from it?
β Edison Flores, AliceLabs LLC