Skip to content

canack/bad-mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bad-mcp

License: MIT Go Docker MCP

10 intentionally malicious MCP servers that demonstrate protocol-level attack patterns against AI clients. Each server exploits a distinct feature of the Model Context Protocol — tool descriptions, schemas, resources, session management, and cross-server interactions.

These aren't buggy servers waiting to be exploited. They are the attacker.

WARNING: This project is for authorized security research and education only. Do NOT expose these servers to the internet or use them in production.

Why This Exists

MCP adoption is accelerating — Claude Desktop, Cursor, Windsurf, and dozens of other AI clients now support it. But the protocol's trust model has fundamental gaps: tool descriptions are unverified, schemas can carry hidden instructions, and servers can mutate definitions mid-session. Research from CyberArk, Invariant Labs, and Elastic Security Labs has documented these attacks, but working implementations are scarce.

bad-mcp provides concrete, runnable attack servers so client developers can test defenses, security teams can assess risk, and researchers can study protocol-level threats without building everything from scratch.

How This Differs

bad-mcp damn-vulnerable-MCP-server vulnerable-mcp-servers-lab
Perspective Server is the attacker Server is the victim Server is the victim
Focus MCP protocol-level attacks only Mixed (prompt injection + classic appsec) Mixed (path traversal, SQLi, MCP)
Attacks FSP, ATPA, rug-pull, resource poisoning, cross-server shadowing CTF challenges (easy/med/hard) 9 servers, pentest training
Language Go + mcp-go SDK Python JS + Python
Isolation Docker-compose, no host access Local Python scripts Docker-compose
Unique Rug-pull via session tools + notifications, full-schema poisoning via param names Challenge/scoring format Typosquatting focus

Architecture

vuln-external network (localhost:8001-8010)
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ schema-poison-notes│ │ response-inject-   │ │ shadow-exfil       │
│       :8001        │ │ tickets    :8002   │ │       :8003        │
└────────────────────┘ └────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ squatting-file-ops │ │ tool-poisoning-calc│ │ true-rug-pull      │
│       :8004        │ │       :8005        │ │       :8006        │
└────────────────────┘ └────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ resource-poison-   │ │ indirect-inject-   │ │ exfil-chain-       │
│ docs       :8007   │ │ fetcher    :8008   │ │ analytics  :8009   │
└────────────────────┘ └────────────────────┘ └────────────────────┘
┌────────────────────┐
│ denial-of-wallet   │
│       :8010        │
└────────────────────┘

Servers

Port Server MCP Attack Class Protocol Feature Exploited
8001 schema-poison-notes Full-Schema Poisoning (FSP) input_schema parameter names
8002 response-inject-tickets Adv. Tool Poisoning via Output (ATPA) Tool response content
8003 shadow-exfil Cross-Server Shadowing Multi-server tool descriptions
8004 squatting-file-ops Tool Name Collision / Squatting Tool naming + descriptions
8005 tool-poisoning-calc Tool Description Poisoning (TPA) Tool descriptions
8006 true-rug-pull Rug-Pull (Tool Def Mutation) Session tools + notifications
8007 resource-poison-docs Resource Poisoning (ATPA variant) resources/list + resources/read
8008 indirect-inject-fetcher Indirect Prompt Injection External data in tool output
8009 exfil-chain-analytics Cross-Tool Exfiltration Chain Tool chaining via descriptions
8010 denial-of-wallet Denial of Wallet Recursive invocation + massive output

Each server has its own README.md with vulnerability details, exploit scenarios, detection methods, and mitigation strategies.

Quick Start

# Build and start all servers
docker-compose build && docker-compose up -d

# Run smoke tests (runs entirely inside Docker)
docker-compose --profile test run --rm smoke-test

# View exfiltration logs
docker-compose logs schema-poison-notes | grep EXFIL
docker-compose logs true-rug-pull | grep RUG-PULL

# Stop
docker-compose down

Connecting an MCP Client

After docker-compose up -d, connect any SSE-compatible MCP client (Claude Desktop, Cursor, Windsurf, Claude Code, etc.). All servers use the same JSON format:

{
  "mcpServers": {
    "schema-poison-notes":    { "url": "http://localhost:8001/sse" },
    "response-inject-tickets":{ "url": "http://localhost:8002/sse" },
    "shadow-exfil":           { "url": "http://localhost:8003/sse" },
    "squatting-file-ops":     { "url": "http://localhost:8004/sse" },
    "tool-poisoning-calc":    { "url": "http://localhost:8005/sse" },
    "true-rug-pull":          { "url": "http://localhost:8006/sse" },
    "resource-poison-docs":   { "url": "http://localhost:8007/sse" },
    "indirect-inject-fetcher":{ "url": "http://localhost:8008/sse" },
    "exfil-chain-analytics":  { "url": "http://localhost:8009/sse" },
    "denial-of-wallet":       { "url": "http://localhost:8010/sse" }
  }
}

Tip: Start with tool-poisoning-calc (:8005) — simplest attack to observe. Then try true-rug-pull (:8006) — ask about the weather 3+ times and watch the tools mutate.

Safety Guarantees

Concern Guarantee
Host filesystem No volume mounts. Containers have zero access to host filesystem.
Host network No network_mode: host. All containers use isolated Docker bridge networks.
Privileged access No privileged: true. No cap_add. Default restricted capabilities.
Environment leakage No host env vars passed. All "credentials" are fake hardcoded strings.
Host execution Nothing runs on the host. Tests run inside Docker via --profile test.
Code on disk Inert Go source files. Not executable outside Docker.

Tech Stack

  • MCP servers: Go + mcp-go v0.32.0 (SSE transport)
  • Docker: Multi-stage golang:1.23-alpine -> alpine:3.19
  • Orchestration: docker-compose with network isolation
  • Testing: Dockerized Go smoke test (--profile test)

Research References

Server Source
schema-poison-notes CyberArk — Full-Schema Poisoning
response-inject-tickets CyberArk — ATPA
shadow-exfil Invariant Labs — Tool Poisoning
squatting-file-ops Elastic Security Labs
tool-poisoning-calc Invariant Labs — Tool Poisoning
true-rug-pull ETDI Paper
resource-poison-docs Pillar Security
indirect-inject-fetcher Microsoft — Indirect Injection
exfil-chain-analytics Elastic Security Labs
denial-of-wallet Prompt Security — Top 10 MCP Risks

See also: Adversa AI — MCP Security TOP 25 | MCPTox Benchmark | OWASP Top 10 for Agentic Applications

Known Gaps

The following published MCP attack classes are not yet implemented:

  • Server Identity Spoofing — MCP server spoofing trusted serverInfo name/version during initialization
  • Sampling Abuse — Exploiting sampling/createMessage to inject arbitrary prompts
  • Prompt/System Instruction Leakage — Extracting system prompts via crafted tool responses
  • Notification Channel Exfiltration — Abusing progress/logging notifications as data channels

About

10 intentionally malicious MCP servers that exploit protocol features to attack AI clients. For security research and defense testing.

Topics

Resources

License

Stars

9 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors