T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/cdp-proxy.mjs:90
- Finding
- Unauthenticated Network-Exposed Browser Proxy<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cdp-proxy.mjs:90-132`, with the unrestricted listener at `scripts/cdp-proxy.mjs:241` **Vulnerability Type**: Missing authentication, unrestricted network binding, permissive CORS, and arbitrary browser navigation **Risk Level**: High ### Vulnerable Code ```javascript // CORS headers res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') res.setHeader('Access-Control-Allow-Headers', 'Content-Type') if (req.method === 'OPTIONS') { res.writeHead(200) res.end() return } try { // Health check if (pathname === '/health') { res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ status: 'ok', tabs: tabs.size, chromeConnected: true })) return } // Create a new tab if (pathname === '/new' && req.method === 'GET') { const targetUrl = url.searchParams.get('url') || 'about:blank' const tab = await createNewTab(targetUrl) if (tab) { const tabId = `tab_${nextTabId++}` tabs.set(tabId, { id: tabId, targetId: tab.id, url: tab.url, ws: null }) res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ success: true, tabId, url: tab.url })) } else { res.writeHead(500) res.end(JSON.stringify({ error: 'Failed to create tab' })) } return } ``` ```javascript server.listen(PORT, async () => { ``` ### Technical Analysis Calling `server.listen(PORT)` without specifying a loopback address causes Node.js to listen on available network interfaces. The service implements no authentication or authorization and sets `Access-Control-Allow-Origin` to `*`, allowing arbitrary websites to issue cross-origin requests and read responses. The operational `/new` endpoint accepts an arbitrary URL and forwards it to Chrome's remote-debugging ...[truncated 2087 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Bind the service explicitly to loopback: ```javascript server.listen(PORT, '127.0.0.1', callback) ``` 2. Require a cryptographically random bearer token for every endpoint, including health and tab-listing operations. 3. Replace wildcard CORS with a strict allowlist or disable browser-origin access entirely. 4. Validate `Origin`, `Host`, and `Content-Type` headers and reject cross-site requests by default. 5. Allowlist permitted navigation origins, such as the required Pinduoduo merchant domains, instead of accepting arbitrary URLs. 6. Use unguessable target identifiers and enforce per-client authorization before listing, creating, or closing tabs. 7. Run automation in a dedicated browser profile containing no unrelated authenticated sessions. 8. Keep Chrome's own debugging endpoint bound to loopback and protect it from containers or network namespaces that do not require access. 9. Add request-size limits, rate limits, security logging, and automatic shutdown after the task completes. 10. Do not activate the evaluation, click, or screenshot handlers until equivalent authentication and authorization controls are in place. ]]>
