q-ai ships intentionally vulnerable MCP servers in fixtures/vulnerable_servers/ for scanner validation, CI testing, and learning. Each fixture demonstrates a specific OWASP MCP Top 10 vulnerability category.
Fixture servers
| Fixture | OWASP ID | Vulnerability demonstrated |
|---|
vuln_token_exposure.py | MCP01 | Leaks secrets through tool parameters, responses, error messages, and configuration data |
vuln_permissions.py | MCP02 | Overprivileged tool set with shell execution, file system, database, and credential management |
vuln_tool_poison.py | MCP03 | Poisoned tool descriptions with embedded instructions, hidden Unicode, and homoglyph names |
vuln_supply_chain.py | MCP04 | Reports a known-vulnerable server identity (CVE-2025-49596) with namespace-confused tools |
vuln_injection.py | MCP05 | Passes user input directly to shell commands without sanitization |
vuln_argument_injection.py | MCP05 | Accepts unsanitized subprocess arguments and file paths, enabling argument injection and path traversal |
vuln_prompt_inject.py | MCP06 | Returns tool responses containing prompt injection patterns, suspicious URLs, and cross-tool manipulation |
vuln_auth.py | MCP07 | Exposes sensitive tools with no authentication or authorization controls |
vuln_audit_telemetry.py | MCP08 | Missing version identification, leaks stack traces and credentials in error messages |
vuln_shadow_servers.py | MCP09 | Shadow deployment characteristics with test/debug naming and exposed debug tools |
vuln_context.py | MCP10 | Over-shares context in responses, leaks session identifiers, exposes unscoped resources with credentials |
Running a fixture scan
All fixtures are stdio MCP servers. Scan one with:
qai audit scan \
--transport stdio \
--command "python fixtures/vulnerable_servers/vuln_injection.py"
Run a specific scanner against its matching fixture:
qai audit scan \
--transport stdio \
--command "python fixtures/vulnerable_servers/vuln_auth.py" \
--checks auth
Verify connectivity before scanning:
qai audit enumerate \
--transport stdio \
--command "python fixtures/vulnerable_servers/vuln_injection.py"
Writing custom fixtures
A fixture is any MCP server with intentional vulnerabilities. To create one:
- Write a standard MCP server using
mcp.server.fastmcp.FastMCP
- Register tools that exhibit the vulnerability you want to test
- Run it with
qai audit scan --transport stdio --command "python your_fixture.py"
Follow the existing fixture pattern — each file is a self-contained MCP server that can be spawned via stdio:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-vulnerable-server")
@mcp.tool()
def vulnerable_tool(user_input: str) -> str:
"""A tool with an intentional vulnerability."""
import subprocess
# Intentionally vulnerable: unsanitized shell input
return subprocess.check_output(user_input, shell=True).decode()
if __name__ == "__main__":
mcp.run(transport="stdio")
Custom fixtures are useful for validating scanner behavior against specific vulnerability patterns and for training teams on MCP security risks.