-
-
Notifications
You must be signed in to change notification settings - Fork 69.1k
[Bug]: Browser bridge server has optional authentication #6609
Description
CVSS Assessment
| Metric | Value |
|---|---|
| Score | 7.7 / 10.0 |
| Severity | High |
| Vector | CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
Summary
The browser bridge server's authentication token is optional. When started without an authToken, all browser automation endpoints are exposed without authentication. Local applications or DNS rebinding attacks could gain full control over browser automation, including extracting cookies and session data.
Affected Code
File: src/browser/bridge-server.ts:33-42
export async function startBrowserBridgeServer(params: {
resolved: ResolvedBrowserConfig;
host?: string;
port?: number;
authToken?: string; // OPTIONAL
// ...
}): Promise<BrowserBridge> {
const host = params.host ?? "127.0.0.1";
// ...
const authToken = params.authToken?.trim();
if (authToken) {
app.use((req, res, next) => {
const auth = String(req.headers.authorization ?? "").trim();
if (auth === `Bearer ${authToken}`) {
return next();
}
res.status(401).send("Unauthorized");
});
}
// If no authToken provided, NO auth middleware is added
// All routes are completely unprotectedAttack Surface
How is this reached?
- Network (HTTP/WebSocket endpoint, API call)
- Adjacent Network (same LAN, requires network proximity)
- Local (local file, CLI argument, environment variable)
- Physical (requires physical access to machine)
Authentication required?
- None (unauthenticated/public access)
- Low (any authenticated user)
- High (admin/privileged user only)
Entry point: HTTP endpoints on the browser bridge server (default: localhost).
Exploit Conditions
Complexity:
- Low (no special conditions, works reliably)
- High (requires race condition, specific config, or timing)
User interaction:
- None (automatic, no victim action needed)
- Required (victim must click, visit, or perform action)
Prerequisites:
- Browser bridge server running without authToken
- Attacker can make HTTP requests to localhost (malicious local app or DNS rebinding)
Impact Assessment
Scope:
- Unchanged (impact limited to vulnerable component)
- Changed (can affect other components, escape sandbox)
What can an attacker do?
| Impact Type | Level | Description |
|---|---|---|
| Confidentiality | High | Extract cookies, localStorage, sessionStorage from browser sessions |
| Integrity | High | Control browser automation - navigate, click, execute JavaScript |
| Availability | None | No direct service disruption |
Attack scenarios:
-
Malicious local application: A trojan or malicious Electron app on the same machine makes requests to the bridge server, extracting all browser session cookies.
-
DNS rebinding:
- User visits attacker's website
- JavaScript performs DNS rebinding to resolve attacker's domain to 127.0.0.1
- Attacker's script gains same-origin access to bridge server
- Extracts cookies and controls browser
Steps to Reproduce
- Start browser bridge server without authToken configured
- From any local process, call the browser control API:
# Get all cookies curl http://localhost:8080/api/cookies # Navigate browser to malicious site curl -X POST http://localhost:8080/api/navigate \ -H "Content-Type: application/json" \ -d '{"url":"https://evil.com"}' # Execute arbitrary JavaScript curl -X POST http://localhost:8080/api/evaluate \ -H "Content-Type: application/json" \ -d '{"script":"document.cookie"}'
- Observe: Full browser control without any authentication
Recommended Fix
-
Make authToken required:
export async function startBrowserBridgeServer(params: { authToken: string; // Required, generate random token if not provided // ... }): Promise<BrowserBridge> { if (!params.authToken?.trim()) { throw new Error('Browser bridge requires authToken for security'); }
-
Or auto-generate a random token if not provided:
const authToken = params.authToken?.trim() || crypto.randomUUID(); console.log(`Browser bridge auth token: ${authToken}`); // Always add auth middleware app.use((req, res, next) => { const auth = String(req.headers.authorization ?? "").trim(); if (auth === `Bearer ${authToken}`) { return next(); } res.status(401).send("Unauthorized"); });
-
Add Host header validation to prevent DNS rebinding even with auth.
References
- CWE: CWE-306 - Missing Authentication for Critical Function
- Related: Browser automation security, DNS rebinding attacks