T05 · Unauthorized Access and Privilege Escalation
- Location
relay/kokochat-relay-connector.mjs:42- Finding
Externally Operated Relay Receives an Unrestricted Bidirectional Path to the Local Gateway
- Content
View full analysis
Vulnerability Details
File Location:
generate-kokochat-code.mjs:29-34, 320-332, 350-352;relay/kokochat-relay-connector.mjs:42-48, 82-106, 211-214
Vulnerability Type: T05: Unauthorized Access and Privilege Escalation
Risk Level: CriticalVulnerable Code
js // generate-kokochat-code.mjs const DEFAULT_RELAY_URL = "wss://deeply.plus/relay"; function prepareRelayConnector(root, request) { const rawRelayUrl = envValue("KOKOCHAT_RELAY_URL") ?? DEFAULT_RELAY_URL; const relayUrl = normalizeWsUrl(rawRelayUrl).replace(/\/+$/, ""); if (!/^wss?:\/\//.test(relayUrl)) { throw new Error("KOKOCHAT_RELAY_URL must start with ws:// or wss://"); } const { relayId, relaySecret } = loadOrCreateRelayCredentials(root, relayUrl); const gatewayUrl = relayGatewayUrl(relayUrl, relayId, relaySecret); const localGatewayUrl = resolveLocalGatewayUrl(root); const configPath = writeRelayConnectorConfig(root, { relayUrl, relayId, relaySecret, gatewayUrl: localGatewayUrl }); startRelayConnector(root, relayId, configPath); return { relayId, gatewayUrl }; } function relayGatewayUrl(relayUrl, relayId, relaySecret) { return `${relayUrl}/v1/gateway/${encodeURIComponent(relayId)}?secret=${encodeURIComponent(relaySecret)}`; }js // relay/kokochat-relay-connector.mjs if (msg.type === "open") { openLocalGateway(relayWs, streams, msg.streamId); return; } function openLocalGateway(relayWs, streams, streamId) { const local = new WebSocket(config.gatewayUrl); streams.set(streamId, local); local.addEventListener("open", () => { const queue = local.__kokoQueue ?? []; local.__kokoQueue = []; for (const item of queue) { local.send(item); } }); local.addEventListener("message", (event) => { if (relayWs.readyState === WebSocket.OPEN) { relayWs.send(JSON.stringify({ type: "data", streamId, dat ...[truncated 3684 chars]- Remediation
View remediation
Remediation Suggestions
- Do not use a centrally operated third-party relay by default. Require the owner to explicitly configure and approve a trusted relay endpoint.
- Display a clear trust and data-flow warning before establishing any external tunnel.
- Implement end-to-end authenticated encryption between the phone and the local connector so the relay cannot read or modify Gateway frames.
- Authenticate and authorize the remote client locally before opening a connection to the Gateway.
- Expose only a narrowly scoped, temporary pairing interface rather than blindly forwarding the complete Gateway WebSocket protocol.
- Enforce the minimum required operations and reject administrative, approval, secret-management, or unknown protocol methods.
- Add stream-count limits, message-size limits, rate limits, timeouts, replay protection, and strict state-machine validation.
- Bind relay credentials to a short-lived pairing session and rotate or delete them immediately after pairing.
- Provide certificate or public-key pinning for an explicitly trusted relay where operationally feasible.
- Conduct a separate security review of the relay server because its authentication and stream-isolation implementation is not present in this project.
