Bug
REAP’s unauthenticated-exposure probes reuse the session that was initialized with --auth-header.
probe.WithNoAuth() only suppresses a per-request Authorization header. It does not establish a separate anonymous transport/session. As a result, REAP can report authenticated access as unauthenticated exposure.
Confirmed WebSocket case
This is directly reproducible for the WebSocket transport:
-
Run REAP against an MCP endpoint over WebSocket with --auth-header.
-
The WebSocket upgrade succeeds using those credentials.
-
mcp-unauth-tools-list calls:
s.Do(ctx, "tools/list", map[string]any{}, probe.WithNoAuth())
-
In WSSession.Do(), request options—including WithNoAuth()—are intentionally ignored because authentication is established during the WebSocket handshake.
-
If tools/list succeeds, REAP can report that the tool list is accessible without authentication, even though the connection was authenticated.
Affected probes
mcp-unauth-tools-list
mcp-resources-prompts-exposure
- OAuth Bearer-challenge detection, which also issues
tools/list with WithNoAuth()
Related transport state
The same approach may also be unsafe for other transports:
- Streamable HTTP retains
Mcp-Session-Id captured during authenticated initialization.
- Legacy HTTP+SSE retains an authenticated long-lived SSE connection.
Expected behavior
A finding described as “unauthenticated” should be based on a separate anonymous connection/session, without credentials or state established by an authenticated connection.
Actual behavior
On WebSocket, WithNoAuth() cannot make a request anonymous after an authenticated upgrade. The scanner may emit false high-confidence unauthenticated-exposure findings.
Suggested direction
Run authentication-sensitive probes through a separate unauthenticated session/connection, or exclude transports where an anonymous per-request request cannot be represented safely.
Regression test
Add an authentication-required WebSocket MCP test server:
- Require credentials during WebSocket upgrade.
- Return a non-empty
tools/list result only on authenticated connections.
- Scan with
--auth-header.
- Verify that REAP does not emit an unauthenticated-exposure finding.
Bug
REAP’s unauthenticated-exposure probes reuse the session that was initialized with
--auth-header.probe.WithNoAuth()only suppresses a per-requestAuthorizationheader. It does not establish a separate anonymous transport/session. As a result, REAP can report authenticated access as unauthenticated exposure.Confirmed WebSocket case
This is directly reproducible for the WebSocket transport:
Run REAP against an MCP endpoint over WebSocket with
--auth-header.The WebSocket upgrade succeeds using those credentials.
mcp-unauth-tools-listcalls:In
WSSession.Do(), request options—includingWithNoAuth()—are intentionally ignored because authentication is established during the WebSocket handshake.If
tools/listsucceeds, REAP can report that the tool list is accessible without authentication, even though the connection was authenticated.Affected probes
mcp-unauth-tools-listmcp-resources-prompts-exposuretools/listwithWithNoAuth()Related transport state
The same approach may also be unsafe for other transports:
Mcp-Session-Idcaptured during authenticated initialization.Expected behavior
A finding described as “unauthenticated” should be based on a separate anonymous connection/session, without credentials or state established by an authenticated connection.
Actual behavior
On WebSocket,
WithNoAuth()cannot make a request anonymous after an authenticated upgrade. The scanner may emit false high-confidence unauthenticated-exposure findings.Suggested direction
Run authentication-sensitive probes through a separate unauthenticated session/connection, or exclude transports where an anonymous per-request request cannot be represented safely.
Regression test
Add an authentication-required WebSocket MCP test server:
tools/listresult only on authenticated connections.--auth-header.