T09 · Insecure Skill Coding Practices
Error
- Location
- src/dashboard.js:492
- Finding
- Unauthenticated Network Exposure of Logs and Operational Data<![CDATA[ ## Vulnerability Details **File Location**: `src/dashboard.js:492-518` **Vulnerability Type**: Unauthenticated monitoring API exposure and unsafe default network binding **Risk Level**: High ### Vulnerable Code ```javascript const server = http.createServer((req, res) => { if (req.url === '/' || req.url === '/dashboard') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(dashboardHTML); } else if (req.url === '/api/status') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.getStatus(), null, 2)); } else if (req.url === '/api/metrics') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.exportMetrics(), null, 2)); } else if (req.url === '/api/logs') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.exportLogs({ limit: 100 }))); } else if (req.url === '/api/prometheus') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(obs.exportMetrics('prometheus')); } else if (req.url === '/api/alerts') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.getAlertHistory({ limit: 50 }), null, 2)); } else { res.writeHead(404); res.end('Not Found'); } }); const PORT = process.env.OBSERVABILITY_PORT || 3001; server.listen(PORT, () => { ``` ### Technical Analysis The dashboard exposes system status, metrics, logs, Prometheus data, and alert history without authentication or authorization. The HTTP server also calls `server.listen(PORT)` without specifying a host. In Node.js, omitting the host normally causes the server to listen on an unspecified address, potentially accepting connections through non-loopback interfaces. This conflicts with the console output and documentation suggesting that the service is available only through `localhost`. The network exposure is broader than the minimum privileges required for a lo ...[truncated 1984 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Bind the dashboard to loopback by default: ```javascript const HOST = process.env.OBSERVABILITY_HOST || '127.0.0.1'; server.listen(PORT, HOST, () => { console.log(`Observability Dashboard running at http://${HOST}:${PORT}`); }); ``` 2. Require authentication and authorization before returning any dashboard or API response. Use a securely generated API token, authenticated reverse proxy, mutual TLS, or an established identity provider. 3. Apply separate authorization rules to sensitive endpoints. In particular, restrict `/api/logs` and `/api/alerts` more heavily than aggregate metrics. 4. Require TLS whenever the service is exposed beyond loopback. Do not transmit authentication tokens or monitoring data over plaintext HTTP. 5. Implement structured redaction before data is logged or exported. At minimum, redact fields matching names such as `authorization`, `cookie`, `token`, `secret`, `password`, `apiKey`, and `credential`. 6. Make log export disabled by default and require an explicit configuration option to enable it. 7. Add deployment documentation warning that binding to `0.0.0.0` or `::` exposes monitoring information to the network. 8. Add tests confirming that: - The default listener is loopback-only. - Unauthenticated requests are rejected. - Users without log-viewing permission cannot access `/api/logs`. - Sensitive metadata is redacted. ]]>
