T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- src/bridge/http.ts:146
- Finding
- Unauthenticated bridge clients inherit the privileged upstream credential<![CDATA[ ## Vulnerability Details **File Location**: `src/bridge/http.ts:146-152` **Vulnerability Type**: Missing client authentication and credential-boundary violation **Risk Level**: High ### Vulnerable Code ```ts function getRemoteConfig(req: http.IncomingMessage, options: BridgeCliOptions): RemoteConfig { const resolved = resolveConfig({ remoteUrl: options.remoteUrl, }); return { token: extractBearerToken(req) ?? resolved.token, remoteUrl: resolved.remoteUrl, }; } ``` The resulting configuration is used by both discovery and invocation endpoints: ```ts if (req.method === "GET" && url.pathname === "/mcp/tools") { const tools = await listExposedTools(getRemoteConfig(req, options)); writeJson(res, 200, { tools }); return; } if (req.method === "POST" && url.pathname.startsWith("/mcp/tools/")) { const toolName = decodeURIComponent(url.pathname.slice("/mcp/tools/".length)); // ... await handleToolInvocation(req, res, toolName, options); return; } ``` ### Technical Analysis The bridge treats a missing client `Authorization` header as permission to use the process-wide upstream token from `MY_MCP_TOKEN` or `OPENCLAW_TOKEN`. This conflates two distinct trust boundaries: 1. Authentication between a client and the local bridge. 2. Authentication between the bridge and the upstream MCP service. The upstream credential should not implicitly authenticate arbitrary bridge clients. Although the default listener is `127.0.0.1`, the CLI supports an arbitrary `--host` value. Local untrusted processes can also reach a loopback listener. No independent authentication or tool-level authorization is enforced before remote tools are listed or invoked. ### Attack Path 1. The operator starts the bridge with a valid upstream token. 2. The bridge is reachable by an untrusted local process or is bound to a network-accessible interface using `--host`. 3. The attacker sends `GET /mcp/tools` without an `Authorization` header. 4. `getRemoteCon ...[truncated 696 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Require independent client authentication for every endpoint except, if necessary, `/health`. - Never use the upstream MCP token as a fallback client credential. - Return `401 Unauthorized` when client authentication is absent or invalid. - Use a separate bridge-access token or authenticated local IPC mechanism. - Add per-client and per-tool authorization so callers receive only the tools required for their task. - Refuse non-loopback binding by default. Require an explicit unsafe-network acknowledgement and configured authentication before accepting `--host 0.0.0.0` or another non-loopback address. - Add rate limiting, request-size limits, and security logging for failed authentication and tool invocation. ]]>
