T09 · Insecure Skill Coding Practices
- Location
src/server.js:115- Finding
Unauthenticated API Endpoints Act as a Privileged OpenClaw Gateway Proxy
- Content
View full analysis
{ if (!OPENCLAW_GATEWAY_TOKEN) { return res.status(500).json({ ok: false, error: 'OPENCLAW_GATEWAY_TOKEN not set' }); } let messages; if (req.body?.messages?.length) { messages = req.body.messages; } else { const text = String(req.body?.text || '').trim(); if (!text) return res.status(400).json({ ok: false, error: 'text or messages required' }); messages = [{ role: 'user', content: text }]; } // SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.flushHeaders(); const sendEvent = (obj) => res.write(`data: ${JSON.stringify(obj)}\n\n`); try { const upstream = await fetch(`${OPENCLAW_GATEWAY_URL}/v1/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${OPENCLAW_GATEWAY_TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model: OPENCLAW_MODEL, user: 'voiceclaw', messages, stream: true }), }); ``` The non-streaming endpoint has the same access-control issue: ```js // POST /api/chat { text } → OpenClaw Gateway → { reply } app.post('/api/chat', async (req, res) => { try { if (!OPENCLAW_GATEWAY_TOKEN) { return res.status(500).json({ ok: false, error: 'OPENCLAW_GATEWAY_TOKEN not set' }); } // Accept { messages } (full history) or { text } (single turn) let messages; if (req.b ...[truncated 3780 chars]- Remediation
View remediation
