T05 · Unauthorized Access and Privilege Escalation
- Location
src/api/routes.ts:20- Finding
Privileged Local API Does Not Authenticate Callers
- Content
View full analysis
{ if (req.url === "/health") return; const key = getApiKey(); if (!key) { return reply.code(401).send({ error: "api_key_required", message: "No API key configured. Restart the server to auto-register, or run: bash scripts/setup.sh", docs_url: "https://unbrowse.ai", }); } }); ``` A representative privileged route is: ```ts // POST /v1/auth/steal — extract cookies from Chrome/Firefox SQLite DBs. // No browser launch, Chrome can stay open. Higher rate limit since it's instant. app.post("/v1/auth/steal", { config: { rateLimit: { max: 30, timeWindow: "1 minute" } } }, async (req, reply) => { const { url, chrome_profile, firefox_profile } = req.body as { url: string; chrome_profile?: string; firefox_profile?: string; }; if (!url) return reply.code(400).send({ error: "url required" }); try { const domain = new URL(url).hostname; const result = await extractBrowserAuth(domain, { chromeProfile: chrome_profile, firefoxProfile: firefox_profile, }); return reply.send(result); } catch (err) { return reply.code(500).send({ error: (err as Error).message }); } }); ``` ### Technical Analysis The request hook verifies only whether the server process has an Unbrowse backend API key. It does not authenticate the process or user sending the HTTP request to the local service. Consequently, once the server has registered, every process capable of reaching port 6969 is treated as authorized. This includes rout ...[truncated 1378 chars]- Remediation
View remediation
