T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- server.js:676
- Finding
- <![CDATA[Unauthenticated TTS Gateway Exposed on All Network Interfaces]]><![CDATA[ ## Vulnerability Details **File Location**: `server.js:676-814` **Vulnerability Type**: Missing authentication and authorization on a network-exposed service **Risk Level**: High ### Vulnerable Code ```js const server = http.createServer(async (req, res) => { try { if (req.method === 'GET' && req.url === '/health') { return sendJson(res, 200, { status: 'ok', port: config.port }); } if (req.method === 'GET' && req.url.startsWith('/api/session/state')) { const url = new URL(req.url, 'http://127.0.0.1'); const sessionId = url.searchParams.get('sessionId') || config.openclawSession; const userId = url.searchParams.get('userId') || 'anonymous'; const current = getSessionState(sessionId, userId).session; return sendJson(res, 200, { success: true, session: current }); } if (req.method === 'POST' && req.url === '/api/workflow/message') { const body = await readJsonBody(req); const result = await handleWorkflowMessage(body || {}); return sendJson(res, 200, result); } if (req.method === 'POST' && req.url === '/api/tts/custom-speak') { const body = await readJsonBody(req); const result = await synthesizeCustomVoice({ text: body.text, style: body.style || '普通', language: body.language || config.defaultLanguage, speakerId: body.speakerId || config.defaultSpeaker, }); return sendJson(res, 200, { success: true, ...result }); } if (req.method === 'POST' && req.url === '/api/tts/clone-speak') { const body = await readJsonBody(req); const result = await synthesizeClonedVoice({ text: body.text, referenceAudioPath: body.referenceAudioPath, language: body.language || config.defaultLanguage, referenceText: body.referenceText || '', }); return sendJson(res, 200, { success: true, ...result }); } return sendJson(res, 404, { success: false, error: 'not found' }) ...[truncated 2489 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Bind the gateway to loopback by default: ```js server.listen(config.port, '127.0.0.1', () => { // ... }); ``` 2. If remote access is required, require an unpredictable bearer token or mutually authenticated TLS before processing any `/api/*` route. 3. Authorize session access using trusted identity supplied by the authenticated OpenClaw integration; do not treat caller-selected `userId` or `sessionId` values as proof of identity. 4. Restrict port 9002 using host firewall rules and network access-control lists. 5. Put remote deployments behind a TLS-enabled reverse proxy. 6. Add request-rate, inference-concurrency, and per-user quota controls. 7. Return only necessary session fields and avoid disclosing absolute filesystem paths. ]]>
