hackwither_

reap / range

reap-range

A deliberately vulnerable MCP server, and a correctly configured mirror of it, for practising agent recon and checking that a scanner’s silence means what it says.

Quick start

git clone https://github.com/hackwither/reap-range && cd reap-range
docker build -t reap-range .
docker run --rm -p 8080:8080 -p 8090:8090 reap-range
targetportpathsposture
bad8080/mcp, /mcp/gatedDeliberately insecure
good8090/mcpCorrectly configured mirror

No Docker? python3 server.py runs it with the standard library only.

Three scans

Open. The insecure target lights up most checks in one scan.

14 of 17 checks match

reap -t http://localhost:8080/mcp --authorized
 REAP  /  AI AGENT RECON
 ────────────────────────────────────────────────────────────────────
 v0.1.2-dev+ad8ce39

 TARGET
 http://localhost:8080/mcp
 ::1  •  MCP 2025-06-18  •  http-streamable  •  CONFIRMED
 Agent       reap-range 0.1.0
 Edge        Werkzeug/3.0 Python/3.12.3
 Discovery   mcp-http-streamable  •  high confidence
 Auth        open  •  enumeration answered without credentials
 Surface     3 tools  •  1 resources  •  1 prompts

 FINDINGS  15 matched  •  use -v for full evidence

 HIGH mcp-unauth-tools-list  HIGH CONFIDENCE
 MCP tool listing accessible without authentication
 tools/list returned 3 tool(s) to an unauthenticated caller: exec_shell, search_tools, run_tool
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  783 B
 OWASP       ASI02: Tool Misuse and Exploitation, ASI03: Identity and Privilege Abuse
 Fix         Require authentication before tools/list, or scope the response so anonymous callers see nothing.

 HIGH mcp-host-header-validation  HIGH CONFIDENCE
 MCP accepted initialize with a mismatched Host header
 The server processed an initialize request even though the Host header was set to "host-header-validation.invalid", so it does not validate the requested host name before handling MCP traffic. This is the condition DNS-rebinding protection prevents; it is rated high only for loopback endpoints, where a browser-driven rebinding attack reaches a local agent directly.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  329 B
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Validate the Host header or equivalent request target before accepting MCP requests, and refuse requests whose host name does not match the configured endpoint.

 HIGH mcp-dynamic-dispatch  MEDIUM CONFIDENCE
 Enumerated MCP tool surface is likely incomplete (dynamic dispatch detected)
 Discovery tool(s) search_tools and executor tool(s) run_tool were detected. This indicates tools/list likely undercounts the real capability surface because callable tools can be reached through search + dispatch.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  783 B
 OWASP       ASI09: Human-Agent Trust Exploitation
 Fix         Expose a complete dispatchable tool manifest or provide a discoverable read-only tool inventory (for example, an extended list endpoint) so downstream security tooling can account for the full surface.

 HIGH http-cors-wildcard
 Permissive CORS policy on agent endpoint
 Server returns Access-Control-Allow-Origin: * — any web origin can call this endpoint from a browser context. Combined with Access-Control-Allow-Credentials: true, this allows credentialed cross-origin requests, which browsers should normally block.
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Scope Access-Control-Allow-Origin to known first-party origins; never reflect an arbitrary Origin, and never combine * with credentialed requests.

 MED mcp-redirect-uri-laxity  MEDIUM CONFIDENCE
 OAuth redirect URI registration appears overly broad
 The discovered OAuth metadata includes redirect URIs that are broad or wildcarded, which increases the risk of confused-deputy or open redirect abuse.
 Evidence    GET http://localhost:8080/.well-known/oauth-authorization-server → 200
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Restrict registered redirect URIs to exact allowed origins and paths, and avoid wildcards or overly permissive URL patterns.

 MED mcp-session-id-entropy  HIGH CONFIDENCE
 MCP session ID entropy looks weak or predictable
 The MCP session ID returned by the server appears to have low entropy or a predictable format: session ID is shorter than 16 characters, estimated entropy is low (36 bits)
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Use a cryptographically random, high-entropy session identifier for MCP sessions and avoid sequential or human-readable formats.

 MED transport-plaintext
 Agent endpoint served over plaintext HTTP
 Target URL uses http:// rather than https://. Tool calls, arguments, and any auth tokens are visible to on-path observers.
 OWASP       ASI07: Insecure Inter-Agent Communication
 Fix         Serve agent endpoints over TLS only; redirect or refuse plaintext connections.

 MED mcp-tmpl-high-risk-tool-names  HIGH CONFIDENCE
 Tool list includes names suggesting code execution or filesystem access
 The tool list (requested with credentials, if any were supplied) includes a tool name matching patterns associated with code-execution or raw-filesystem primitives. This is a triage signal for closer review; verify the tool's actual capabilities and authorization model.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  783 B
 OWASP       ASI02: Tool Misuse and Exploitation, ASI05: Unexpected Code Execution (RCE)
 Fix         Review tool capabilities in context. If the tool performs code execution or unrestricted filesystem access, scope it behind explicit, auditable authorization separate from general tool listing. Consider narrower alternatives.

 LOW mcp-oauth-metadata-posture  HIGH CONFIDENCE
 Published OAuth metadata does not advertise PKCE
 OAuth metadata was published at /.well-known/oauth-authorization-server, but it does not advertise PKCE (code_challenge_methods_supported) support.
 Evidence    GET http://localhost:8080/.well-known/oauth-authorization-server → 200  •  application/json
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Advertise PKCE support (code_challenge_methods_supported: ["S256"]) in published OAuth authorization-server metadata.

 LOW mcp-instructions-exposure  MEDIUM CONFIDENCE
 MCP handshake returns lengthy or sensitive-flavored instructions
 The initialize response's 'instructions' field is long and/or contains language patterns (secrecy directives, 'internal', credential-related terms) worth a human review to confirm it isn't leaking operational or internal detail to any caller.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  329 B
 OWASP       ASI09: Human-Agent Trust Exploitation
 Fix         Keep client-facing instructions limited to usage guidance; keep anything sensitive out of fields returned pre-authentication.

 LOW mcp-resources-prompts-exposure-resources-list  HIGH CONFIDENCE
 Unauthenticated resources/list returns 1 item(s)
 resources/list succeeded without credentials and returned 1 item(s) to an anonymous caller.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  101 B
 OWASP       ASI02: Tool Misuse and Exploitation
 Fix         Gate resource/prompt listings behind authentication if their contents aren't meant to be public.

 LOW mcp-resources-prompts-exposure-prompts-list  HIGH CONFIDENCE
 Unauthenticated prompts/list returns 1 item(s)
 prompts/list succeeded without credentials and returned 1 item(s) to an anonymous caller.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  117 B
 OWASP       ASI02: Tool Misuse and Exploitation
 Fix         Gate resource/prompt listings behind authentication if their contents aren't meant to be public.

 LOW http-rate-limit-absence
 No standard rate-limit headers observed
 The endpoint answered requests but sent no standard rate-limit response headers. This is a reconnaissance signal that the service may not be advertising rate limiting to clients; it is not proof that no limiting exists.
 OWASP       ASI08: Cascading Failures
 Fix         Expose standard rate-limit headers such as Retry-After, RateLimit-Remaining, and RateLimit-Limit, or document the expected client behavior when limits are reached.

 INFO mcp-tool-capability-surface  HIGH CONFIDENCE
 Tool capability inventory (3 tools)
 Full tool surface exposed by this endpoint, for asset-inventory and diffing purposes.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  783 B
 OWASP       ASI09: Human-Agent Trust Exploitation

 INFO mcp-tmpl-server-header-fingerprint  MEDIUM CONFIDENCE
 Server response header discloses backend/edge software
 The response includes a Server or X-Powered-By header identifying backend software that appears to be the origin application, not a CDN/edge layer (which is already surfaced separately in the target fingerprint's Edge line). Not a vulnerability by itself, but useful fingerprinting context worth trimming in production.
 Evidence    POST http://localhost:8080/mcp → 200  •  application/json  •  783 B
 OWASP       ASI09: Human-Agent Trust Exploitation
 Fix         Suppress or genericize identifying response headers in production deployments where they name the origin application.

 POSTURE
 HIGH RISK

 17 checks  •  14 matched  •  1 clean  •  2 skipped  •  28ms
 4 high · 4 med · 5 low · 2 info · 0 error

Auth-gated. An endpoint that correctly requires credentials is a recon result, not a tool failure: REAP reports auth-gated and exits 0. This is also the only path where the bearer-challenge check can fire.

reap -t http://localhost:8080/mcp/gated --authorized
 REAP  /  AI AGENT RECON
 ────────────────────────────────────────────────────────────────────
 v0.1.2-dev+ad8ce39

 TARGET
 http://localhost:8080/mcp/gated
 ::1  •  MCP  •  http-streamable  •  CONFIRMED (AUTH-GATED)
 Edge        Werkzeug/3.0 Python/3.12.3
 Discovery   mcp-http-streamable-version-mismatch-auth-gated  •  low confidence
 Auth        auth-gated  •  live, but requires credentials to enumerate

 ⓘ AUTH REQUIRED
 initialize requires auth: HTTP 401 (application/problem+json, JSON-RPC error envelope)

 FINDINGS  7 matched  •  use -v for full evidence

 MED mcp-oauth-bearer-challenge-missing  HIGH CONFIDENCE
 Protected resource does not send a Bearer WWW-Authenticate challenge
 An unauthenticated tools/list request returned 401, but its WWW-Authenticate header did not include a Bearer challenge (got "").
 Evidence    POST http://localhost:8080/mcp/gated → 401  •  application/json  •  92 B
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Send a WWW-Authenticate: Bearer challenge (optionally with a resource_metadata parameter per RFC 9728) on unauthenticated requests to protected MCP endpoints.

 MED mcp-redirect-uri-laxity  MEDIUM CONFIDENCE
 OAuth redirect URI registration appears overly broad
 The discovered OAuth metadata includes redirect URIs that are broad or wildcarded, which increases the risk of confused-deputy or open redirect abuse.
 Evidence    GET http://localhost:8080/.well-known/oauth-authorization-server → 200
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Restrict registered redirect URIs to exact allowed origins and paths, and avoid wildcards or overly permissive URL patterns.

 MED transport-plaintext
 Agent endpoint served over plaintext HTTP
 Target URL uses http:// rather than https://. Tool calls, arguments, and any auth tokens are visible to on-path observers.
 OWASP       ASI07: Insecure Inter-Agent Communication
 Fix         Serve agent endpoints over TLS only; redirect or refuse plaintext connections.

 LOW mcp-oauth-metadata-posture  HIGH CONFIDENCE
 Published OAuth metadata does not advertise PKCE
 OAuth metadata was published at /.well-known/oauth-authorization-server, but it does not advertise PKCE (code_challenge_methods_supported) support.
 Evidence    GET http://localhost:8080/.well-known/oauth-authorization-server → 200  •  application/json
 OWASP       ASI03: Identity and Privilege Abuse
 Fix         Advertise PKCE support (code_challenge_methods_supported: ["S256"]) in published OAuth authorization-server metadata.

 LOW http-rate-limit-absence
 No standard rate-limit headers observed
 The endpoint answered requests but sent no standard rate-limit response headers. This is a reconnaissance signal that the service may not be advertising rate limiting to clients; it is not proof that no limiting exists.
 OWASP       ASI08: Cascading Failures
 Fix         Expose standard rate-limit headers such as Retry-After, RateLimit-Remaining, and RateLimit-Limit, or document the expected client behavior when limits are reached.

 INFO mcp-enumeration-blocked  HIGH CONFIDENCE
 Tool enumeration blocked by authentication
 tools/list returned 401 without credentials — the server correctly gates enumeration behind authentication, so no tool inventory is available from this vantage point.
 Evidence    POST http://localhost:8080/mcp/gated → 401  •  application/json  •  92 B
 OWASP       ASI09: Human-Agent Trust Exploitation

 INFO mcp-tmpl-server-header-fingerprint  MEDIUM CONFIDENCE
 Server response header discloses backend/edge software
 The response includes a Server or X-Powered-By header identifying backend software that appears to be the origin application, not a CDN/edge layer (which is already surfaced separately in the target fingerprint's Edge line). Not a vulnerability by itself, but useful fingerprinting context worth trimming in production.
 Evidence    POST http://localhost:8080/mcp/gated → 401  •  application/json  •  92 B
 OWASP       ASI09: Human-Agent Trust Exploitation
 Fix         Suppress or genericize identifying response headers in production deployments where they name the origin application.

 POSTURE
 MEDIUM RISK

 17 checks  •  6 matched  •  8 clean  •  3 skipped  •  11ms
 0 high · 3 med · 2 low · 2 info · 0 error

Correct. The mirror shows the false-positive floor: everything is silent except one expected, informational finding. transport-plaintext is excluded because the range is plain HTTP.

reap -t http://localhost:8090/mcp --authorized --exclude transport-plaintext
 REAP  /  AI AGENT RECON
 ────────────────────────────────────────────────────────────────────
 v0.1.2-dev+ad8ce39

 TARGET
 http://localhost:8090/mcp
 ::1  •  MCP 2025-06-18  •  http-streamable  •  CONFIRMED
 Agent       reap-range 0.1.0
 Discovery   mcp-http-streamable  •  high confidence
 Auth        auth-gated  •  live, but requires credentials to enumerate

 FINDINGS  1 matched  •  use -v for full evidence

 INFO mcp-enumeration-blocked  HIGH CONFIDENCE
 Tool enumeration blocked by authentication
 tools/list returned 401 without credentials — the server correctly gates enumeration behind authentication, so no tool inventory is available from this vantage point.
 Evidence    POST http://localhost:8090/mcp → 401  •  application/json  •  92 B
 OWASP       ASI09: Human-Agent Trust Exploitation

 POSTURE
 INFORMATIONAL

 16 checks  •  1 matched  •  13 clean  •  2 skipped  •  14ms
 0 high · 0 med · 0 low · 1 info · 0 error

Unedited output of reap 0.1.2-dev+ad8ce39 against a local reap-range.

What each target does

Every rule page lists how the insecure and correct targets behave for that check, for example mcp-host-header-validation. The full feature table and known limitations are in the reap-range README.