MCP Server Security & Performance Analysis — v0.1.0
| Test ID | Severity | Test Name | Description / Details | Duration |
|---|---|---|---|---|
| SECURITY · 49 tests | ||||
| T02-search_cloudflare_documentation-PI-006 | MEDIUM | Injection PI-006 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' echoed the raw injection payload back in its response (PI-006: Backtick injection…Payload (param='query'): '`id`'
Response excerpt: '<result>\n<url>https://developers.cloudflare.com/https://developers.cloudflare.com/workers-ai/models/kimi-k2.5/</url>\n<title></title>\n<text>\n* `id` ` string ` required \n * `type` ` string ` required \n '
Remediation:
Tools should not reflect unsanitised user input verbatim. Echo-back can be exploited to inject instructions into subsequent LLM context windows. |
2057ms |
| T03-01-query-FUZZ-STR-009 | MEDIUM | Fuzz FUZZ-STR-009 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' took 5159 ms on FUZZ-STR-009 (very long string 10k) — potential DoS via slow-proc…Threshold: 5000 ms. Fuzz value type: 'str'. Param type expected: 'string'.
Remediation:
Add input size and type guards before processing. Unbounded processing time on arbitrary inputs is a DoS vector. |
5159ms |
| T07-002-02 | MEDIUM | Malformed Token: Empty bearer token |
Unexpected exception: LocalProtocolErrorIllegal header value b'Bearer '
|
590ms |
| T07-005 | MEDIUM | CORS Misconfiguration |
Server returns 'Access-Control-Allow-Origin: *' — any browser origin can connect to this MCP server.Wildcard CORS — any browser origin can connect to this MCP server
Remediation:
Restrict the CORS origin allowlist to known, trusted domains. A wildcard allows a malicious web page to make authenticated cross-origin calls to this MCP server. |
883ms |
| T07-010 | LOW | Duplicate Initialize (Replay Attack) |
Server accepted a second initialize() call on an already active session. The session remained usable, but the server sta…Double initialize() succeeded.
Post-replay list_tools() succeeded — session is still functional but capabilities or internal state may have been altered.
Remediation:
The server should reject or ignore repeated initialize() calls. Accepting them enables mid-session protocol version downgrade and capability reset attacks. |
191ms |
| T07-013 | LOW | Protocol Version Abuse |
Server did not negotiate a recognised MCP protocol version (version is empty or unknown).
Remediation:
Ensure the server returns a valid protocolVersion in its initialize response (e.g. '2024-11-05'). Clients rely on this to select compatible behaviour. |
0ms |
| T07-001 | INFO | Unauthenticated MCP Access |
Unexpected HTTP status 404 on unauthenticated probe.Unexpected status: 404
|
789ms |
| T07-002-01 | INFO | Malformed Token: Invalid bearer token | HTTP 404 for Invalid bearer token — unable to confirm rejection. | 896ms |
| T07-002-03 | INFO | Malformed Token: Basic auth instead of Bearer | HTTP 404 for Basic auth instead of Bearer — unable to confirm rejection. | 734ms |
| T07-002-04 | INFO | Malformed Token: Wrong API key format | HTTP 404 for Wrong API key format — unable to confirm rejection. | 773ms |
| T07-003 | INFO | Resource URI Path Traversal | Server advertises no resources — path traversal test skipped. | 0ms |
| T07-006 | INFO | Process Privilege Check | Process privilege check requires STDIO transport — skipped (transport='http'). | 0ms |
| T07-007 | INFO | Environment Variable Probe | Environment variable probe requires STDIO transport — skipped (transport='http'). | 0ms |
| T02-search_cloudflare_documentation-PI-001 | PASS | Injection PI-001 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-001 (Classic override) gracefully.Response excerpt: '<result>\n<url>https://developers.cloudflare.com/https://developers.cloudflare.com/waf/detections/ai-security-for-apps/prompt-injection/</url>\n<title></title>\n<text>\n### Why a score instead of a boolea'
|
3025ms |
| T02-search_cloudflare_documentation-PI-002 | PASS | Injection PI-002 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-002 (Newline injection) gracefully.Response excerpt: '<result>\n<url>https://developers.cloudflare.com/https://developers.cloudflare.com/ai-search/configuration/system-prompt/</url>\n<title></title>\n<text>\n# System prompt\n\nSystem prompts allow you to guide'
|
1704ms |
| T02-search_cloudflare_documentation-PI-003 | PASS | Injection PI-003 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-003 (XML tag injection) gracefully.Response excerpt: ''
|
2640ms |
| T02-search_cloudflare_documentation-PI-004 | PASS | Injection PI-004 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-004 (SQL injection probe) gracefully.Response excerpt: ''
|
1919ms |
| T02-search_cloudflare_documentation-PI-005 | PASS | Injection PI-005 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-005 (Shell injection) gracefully.Response excerpt: '<result>\n<url>https://developers.cloudflare.com/https://developers.cloudflare.com/workers/wrangler/commands/general/</url>\n<title></title>\n<text>\n## `auth`\n\n### `auth token`\n\nRetrieve your current aut'
|
1797ms |
| T02-search_cloudflare_documentation-PI-007 | PASS | Injection PI-007 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-007 (Path traversal) gracefully.Response excerpt: ''
|
2463ms |
| T02-search_cloudflare_documentation-PI-008 | PASS | Injection PI-008 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-008 (Right-to-left override unicode) gracefully.Response excerpt: ''
|
2137ms |
| T02-search_cloudflare_documentation-PI-009 | PASS | Injection PI-009 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-009 (Null byte injection) gracefully.Response excerpt: '<result>\n<url>https://developers.cloudflare.com/https://developers.cloudflare.com/workers/best-practices/workers-best-practices/</url>\n<title></title>\n<text>\n// ✅ Good: test the null case explicitly\n\n'
|
2007ms |
| T02-search_cloudflare_documentation-PI-010 | PASS | Injection PI-010 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-010 (BOM character) gracefully.Response excerpt: ''
|
2137ms |
| T02-search_cloudflare_documentation-PI-011 | PASS | Injection PI-011 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-011 (Rug pull attempt) gracefully.Response excerpt: ''
|
1891ms |
| T02-search_cloudflare_documentation-PI-012 | PASS | Injection PI-012 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-012 (Exfiltration instruction) gracefully.Response excerpt: ''
|
1765ms |
| T02-search_cloudflare_documentation-PI-013 | PASS | Injection PI-013 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-013 (Large payload DoS probe 10k) gracefully.Response excerpt: ''
|
2254ms |
| T02-search_cloudflare_documentation-PI-014 | PASS | Injection PI-014 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-014 (Large payload DoS probe 100k) gracefully.Response excerpt: ''
|
5453ms |
| T02-search_cloudflare_documentation-PI-015 | PASS | Injection PI-015 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-015 (Jinja template injection) gracefully.Response excerpt: ''
|
3322ms |
| T02-search_cloudflare_documentation-PI-016 | PASS | Injection PI-016 → search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' handled PI-016 (Python format injection) gracefully.Response excerpt: ''
|
1653ms |
| T03-01-query-FUZZ-STR-001 | PASS | Fuzz FUZZ-STR-001 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' handled FUZZ-STR-001 (empty string) on param 'query' correctly.Response excerpt: "meta=None content=[TextContent(type='text', text='All search methods failed: vector', annotations=None, meta=None)] structuredContent=None isError=True"
|
185ms |
| T03-01-query-FUZZ-STR-002 | PASS | Fuzz FUZZ-STR-002 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' handled FUZZ-STR-002 (single space) on param 'query' correctly.Response excerpt: "meta=None content=[TextContent(type='text', text='All search methods failed: vector', annotations=None, meta=None)] structuredContent=None isError=True"
|
249ms |
| T03-01-query-FUZZ-STR-003 | PASS | Fuzz FUZZ-STR-003 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' handled FUZZ-STR-003 (whitespace only) on param 'query' correctly.Response excerpt: "meta=None content=[TextContent(type='text', text='All search methods failed: vector', annotations=None, meta=None)] structuredContent=None isError=True"
|
190ms |
| T03-01-query-FUZZ-STR-004 | PASS | Fuzz FUZZ-STR-004 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' returned a structured error for FUZZ-STR-004 (null value) on param 'query' — hand…McpError: MCP error -32602: Invalid arguments for tool search_cloudflare_documentation: [
{
"code": "invalid_type",
"expected": "string",
"received": "null",
"path": [
"query"
],
"message": "Expected string, received null"
}
]
|
331ms |
| T03-01-query-FUZZ-STR-005 | PASS | Fuzz FUZZ-STR-005 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' returned a structured error for FUZZ-STR-005 (integer as string field) on param '…McpError: MCP error -32602: Invalid arguments for tool search_cloudflare_documentation: [
{
"code": "invalid_type",
"expected": "string",
"received": "number",
"path": [
"query"
],
"message": "Expected string, received number"
}
]
|
348ms |
| T03-01-query-FUZZ-STR-006 | PASS | Fuzz FUZZ-STR-006 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' returned a structured error for FUZZ-STR-006 (boolean as string field) on param '…McpError: MCP error -32602: Invalid arguments for tool search_cloudflare_documentation: [
{
"code": "invalid_type",
"expected": "string",
"received": "boolean",
"path": [
"query"
],
"message": "Expected string, received boolean"
}
]
|
135ms |
| T03-01-query-FUZZ-STR-007 | PASS | Fuzz FUZZ-STR-007 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' returned a structured error for FUZZ-STR-007 (list as string field) on param 'que…McpError: MCP error -32602: Invalid arguments for tool search_cloudflare_documentation: [
{
"code": "invalid_type",
"expected": "string",
"received": "array",
"path": [
"query"
],
"message": "Expected string, received array"
}
]
|
328ms |
| T03-01-query-FUZZ-STR-008 | PASS | Fuzz FUZZ-STR-008 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' returned a structured error for FUZZ-STR-008 (dict as string field) on param 'que…McpError: MCP error -32602: Invalid arguments for tool search_cloudflare_documentation: [
{
"code": "invalid_type",
"expected": "string",
"received": "object",
"path": [
"query"
],
"message": "Expected string, received object"
}
]
|
208ms |
| T03-01-query-FUZZ-STR-010 | PASS | Fuzz FUZZ-STR-010 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' handled FUZZ-STR-010 (newlines and tabs) on param 'query' correctly.Response excerpt: "meta=None content=[TextContent(type='text', text='All search methods failed: vector', annotations=None, meta=None)] structuredContent=None isError=True"
|
341ms |
| T03-01-query-FUZZ-STR-011 | PASS | Fuzz FUZZ-STR-011 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' handled FUZZ-STR-011 (null byte in string) on param 'query' correctly.Response excerpt: "meta=None content=[TextContent(type='text', text='', annotations=None, meta=None)] structuredContent=None isError=False"
|
1815ms |
| T03-01-query-FUZZ-STR-012 | PASS | Fuzz FUZZ-STR-012 → search_cloudflare_documentation.query |
Tool 'search_cloudflare_documentation' handled FUZZ-STR-012 (all unicode planes) on param 'query' correctly.Response excerpt: "meta=None content=[TextContent(type='text', text='', annotations=None, meta=None)] structuredContent=None isError=False"
|
2564ms |
| T04-001 | PASS | Rug Pull Detection (Mutation Check) | All 2 tool description(s) were stable across two list_tools() calls (3 s apart). | 3147ms |
| T04-002 | PASS | Hidden Instruction Scan | No suspicious patterns found in 2 tool description(s). | 0ms |
| T04-003 | PASS | Cross-Tool Reference Detection | No cross-tool name references found across 2 tool descriptions. | 0ms |
| T04-004 | PASS | Schema Field Injection Check | All 2 tool inputSchema(s) contain only sanctioned JSON Schema fields. | 0ms |
| T04-005 | PASS | Tool Count Stability Check |
Tool count stable at 2 across 5 polls (2.5s window).Counts per poll: [2, 2, 2, 2, 2]
|
2988ms |
| T07-004 | PASS | Credentials in Error Messages |
No credential patterns found in error response for non-existent tool call.Error excerpt: 'MCP error -32602: Tool mcpsafe_nonexistent_tool_probe not found'
|
655ms |
| T07-008 | PASS | Invalid Tool Name Rejection | Server correctly rejected all invalid tool names. | 1875ms |
| T07-009 | PASS | Oversized Argument Rejection | Server correctly rejected oversized tool arguments. | 1130ms |
| T07-011 | PASS | Deeply Nested Argument (JSON Bomb) | Server rejected deeply nested JSON argument. | 1ms |
| T07-012 | PASS | Unicode Homoglyph Tool Name Spoofing | Server rejected homoglyph tool name 'seаrch_cloudflare_documentation' correctly. | 320ms |
| DISCOVERY · 8 tests | ||||
| T01-001 | INFO | Server Identity |
Server did not advertise: name, version. Got name='unknown' version='unknown' protocol='unknown'.
Remediation:
Ensure the MCP server returns a populated 'serverInfo' object in its initialize response (name and version fields). |
0ms |
| T01-002 | PASS | Tool Enumeration |
Discovered 2 tool(s): search_cloudflare_documentation, migrate_pages_to_workers_guide.search_cloudflare_documentation: 'Search the Cloudflare documentation.\n\n\t\tThis tool should be used to answer any q'
migrate_pages_to_workers_guide: 'ALWAYS read this guide before migrating Pages projects to Workers.'
|
0ms |
| T01-003 | PASS | Resource Enumeration | Discovered 0 resource(s). | 0ms |
| T01-004 | PASS | Prompt Enumeration |
Discovered 1 prompt(s): workers-prompt-full.workers-prompt-full: 'Detailed prompt for generating Cloudflare Workers code (and other developer plat' (0 arg(s))
|
0ms |
| T01-005 | PASS | Tool Description Completeness | All 2 tool(s) have non-empty descriptions. | 0ms |
| T01-006 | PASS | Tool Schema Validity | All 2 tool(s) have valid JSON Schema inputSchema. | 0ms |
| T01-007 | PASS | Duplicate Tool Names | All 2 tool name(s) are unique. | 0ms |
| T01-008 | PASS | Tool Description Length | All 2 tool description(s) are within the 2,000-character limit. | 0ms |
| SCHEMA · 7 tests | ||||
| T06-004 | INFO | Return Type Consistency | No tools returned comparable JSON responses — consistency check not applicable. | 0ms |
| T06-001 | PASS | Schema Structural Validity | All 2 tool inputSchema(s) are structurally valid. | 0ms |
| T06-002-search_cloudflare_documentation | PASS | Required Enforcement: search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' correctly raised an error when called with missing required fields.McpError: MCP error -32602: Invalid arguments for tool search_cloudflare_documentation: [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"query"
]
|
340ms |
| T06-003 | PASS | additionalProperties Strictness | All 2 tool(s) have 'additionalProperties': false. | 0ms |
| T06-005 | PASS | Overly Permissive Schema Detection | All 2 tool schema(s) are acceptably strict. | 0ms |
| T06-006-migrate_pages_to_workers_guide | PASS | Description Quality: migrate_pages_to_workers_guide |
Tool 'migrate_pages_to_workers_guide' has an adequate description (66 chars).Description: 'ALWAYS read this guide before migrating Pages projects to Workers.'
|
0ms |
| T06-006-search_cloudflare_documentation | PASS | Description Quality: search_cloudflare_documentation |
Tool 'search_cloudflare_documentation' has an adequate description (541 chars).Description: 'Search the Cloudflare documentation.\n\n\t\tThis tool should be used to answer any question about Cloudflare products or features, including:\n\t\t- Workers, Pages, R2, Images, Stream, D1, Durable Objects, K'
|
0ms |
| PERFORMANCE · 10 tests | ||||
| T08-003-00 | INFO | Resource Read Latency | No resources to benchmark. | 0ms |
| T05-001 | PASS | 10 Simultaneous Calls |
All 10 concurrent calls to 'search_cloudflare_documentation' succeeded with no data leakage.min=1901ms mean=1920ms max=1955ms
|
2259ms |
| T05-002 | PASS | 50 Sequential Rapid Calls |
p50=1957ms p95=2594ms p99=2801ms{
"tool": "search_cloudflare_documentation",
"calls": 50,
"errors": 0,
"min_ms": 1242.21,
"mean_ms": 1944.57,
"max_ms": 2800.98,
"p50_ms": 1957.3,
"p95_ms": 2594.3,
"p99_ms": 2800.98
}
|
97229ms |
| T05-003 | PASS | 100 Concurrent Calls (Stress Test) |
All 100 calls succeeded. Throughput: 5.3 calls/secThroughput: 5.3 calls/sec
|
18710ms |
| T05-004 | PASS | Connection Stability Under Rapid Reconnect |
Tool list consistent across all 5 reconnects: ['migrate_pages_to_workers_guide', 'search_cloudflare_documentation'].Reconnects: 5. Tools per connect: 2.
|
24281ms |
| T08-001-01 | PASS | Baseline Latency: search_cloudflare_documentation |
Tool 'search_cloudflare_documentation': mean=2236ms min=1642ms max=3295ms (5 samples).{
"search_cloudflare_documentation": {
"mean_ms": 2236.29,
"min_ms": 1641.55,
"max_ms": 3294.98,
"samples": [
3294.98,
1641.55,
1914.8,
2512.33,
1817.77
]
}
}
|
11181ms |
| T08-001-02 | PASS | Baseline Latency: migrate_pages_to_workers_guide |
Tool 'migrate_pages_to_workers_guide': mean=270ms min=195ms max=354ms (5 samples).{
"migrate_pages_to_workers_guide": {
"mean_ms": 269.74,
"min_ms": 195.09,
"max_ms": 353.75,
"samples": [
261.27,
195.09,
286.41,
353.75,
252.16
]
}
}
|
1349ms |
| T08-002 | PASS | Tool Discovery Latency |
list_tools() mean=247ms min=157ms max=330ms.{
"list_tools": {
"mean_ms": 247.03,
"min_ms": 157.25,
"max_ms": 330.15,
"samples": [
256.95,
257.46,
330.15,
157.25,
233.32
]
}
}
|
1235ms |
| T08-004 | PASS | Cold Start Detection |
No significant cold-start penalty detected (ratio 0.9×, threshold 10×).Call 1 (cold): 1763ms
Calls 2-5 (warm): 1616ms, 2266ms, 2199ms, 1834ms
Warm mean: 1979ms Ratio: 0.9×
|
9678ms |
| T08-005 | PASS | Latency Degradation Under Load |
Latency stable under load: baseline 1253ms, load p95 2594ms (ratio 2.1×).Baseline mean: 1253ms Load p95: 2594ms Degradation ratio: 2.1×
|
0ms |