T09 · Insecure Skill Coding Practices
- Location
cdp-proxy.mjs:278- Finding
Unauthenticated HTTP API Exposes Privileged Browser Control
- Content
View full analysis
{ const parsed = new URL(req.url, `http://localhost:${PORT}`); const pathname = parsed.pathname; ``` ```js else if (pathname === '/eval') { const sid = await ensureSession(q.target); const body = await readBody(req); const expr = body || q.expr || 'document.title'; const resp = await sendCDP('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true, }, sid); if (resp.result?.result?.value !== undefined) { res.end(JSON.stringify({ value: resp.result.result.value })); } else if (resp.result?.exceptionDetails) { ``` The same unauthenticated server also exposes navigation, clicking, screenshots, file-input manipulation, tab enumeration, and tab closure. ### Technical Analysis The proxy grants callers control over Chrome through the Chrome DevTools Protocol but does not authenticate requests, authorize operations, validate a per-session secret, or enforce trusted `Origin` and `Host` values. The `/eval` endpoint directly passes the request body to `Runtime.evaluate`. Consequently, any process able to connect to the local port can execute arbitrary JavaScript in an attached browser page. Because the Skill is explicitly designed to access authenticated sessions and private content, this API crosses a significant security boundary. Binding the server to `127.0.0.1` reduces direct remote exposure but does not establish authorization. Potential callers include malicious local processes, other users or workloads sharing the network namespace, and browser-originated requests under conditions where localhost access or DNS rebinding is possible. Arbitrary JavaScript evaluation is necessary for some declared automation functions, ...[truncated 1471 chars]- Remediation
View remediation
