T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- src/server.ts:286
- Finding
- Unauthenticated privileged API endpoints are exposed on all network interfaces<![CDATA[ ## Vulnerability Details **File Location**: `src/server.ts:286-460`, `src/server.ts:650` **Vulnerability Type**: Missing authentication and authorization; excessive network exposure **Risk Level**: High ### Vulnerable Code ```ts const app = express(); app.use(express.json()); // Client config endpoint app.get('/api/client-config', (_req: Request, res: Response) => { const clientConfig: ClientConfig = getClientConfig(config); res.json(clientConfig); }); app.post('/api/speaking-done', async (_req: Request, res: Response) => { await setSpeaking(false); res.json({ ok: true }); }); app.post('/api/chat', async (req: Request, res: Response) => { const { message, lang } = req.body; // ... const response = await sendChat(augmented); // ... res.json({ spoken, detail }); }); app.post('/api/send-slack', async (req: Request, res: Response) => { const { text } = req.body; // ... const response = await sendChat( `[SYSTEM] Send the following message via Slack DM to targets: ${targetStr}. Do NOT modify the content, just send it as-is. Reply with just "Sent!" after.\n\n${text}` ); res.json({ ok: true, response }); }); app.post('/api/tts', async (req: Request, res: Response) => { const { text, lang, voiceId: customVoiceId } = req.body; // ... const ttsRes = await fetch( `https://api.elevenlabs.io/v1/text-to-speech/${voiceId}?output_format=pcm_16000`, { method: 'POST', headers: { 'xi-api-key': config.secrets.elevenLabsApiKey, 'Content-Type': 'application/json', }, body: JSON.stringify(ttsBody), } ); // ... }); app.post('/api/send-email', async (req: Request, res: Response) => { const { text } = req.body; // ... const response = await sendChat( `[SYSTEM] Send the following content to ${config.integrations.email.recipient} as an email from ${config.app.name}. Use a suitable subject line based on the content. Do NOT modify the content. Reply with just "Sent!" after ...[truncated 2322 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Bind the server explicitly to loopback by default: ```ts app.listen(PORT, '127.0.0.1', callback); ``` 2. Require authenticated sessions for all `/api/*` routes. 3. Apply per-action authorization, especially to Slack, email, agent, and TTS endpoints. 4. Add CSRF protection and validate `Origin` or `Referer` for browser-originated state-changing requests. 5. Require explicit user confirmation immediately before sending Slack or email messages. 6. Add rate limiting, request quotas, and audit logging. 7. Configure a conservative JSON body-size limit, for example: ```ts app.use(express.json({ limit: '32kb' })); ``` 8. If remote access is required, place the service behind TLS and an authenticated reverse proxy rather than exposing Express directly. ]]>
