-
-
Notifications
You must be signed in to change notification settings - Fork 69.2k
[Bug]: Arbitrary JavaScript execution via browser evaluate endpoint when enabled #4950
Description
Summary
Severity: P0/Critical (Score: 130/150)
CWE: CWE-94 - Improper Control of Generation of Code ('Code Injection')
OWASP: A03:2021 - Injection
File: src/browser/pw-tools-core.interactions.ts:227-257
When evaluateEnabled=true, the browser control server accepts arbitrary JavaScript via the /act endpoint and executes it directly via eval() in the browser context with no sanitization, sandboxing, or scope restriction.
Why this is critical: This is arbitrary code execution in the browser context. While gated by a config flag, once enabled there are zero controls—any JavaScript can read cookies, access localStorage, manipulate the DOM, make fetch requests with the page's credentials, or exfiltrate data. Combined with DNS rebinding (#4949), this becomes remotely exploitable. The eval() pattern is the textbook example of dangerous code injection.
Triage Assessment
| Factor | Value | Score |
|---|---|---|
| Reachability | Config-dependent (requires evaluateEnabled) | 25/40 |
| Impact | Arbitrary code execution in browser | 50/50 |
| Exploitability | Single POST request | 30/30 |
| Verification | file:line ✓, code ✓, attack steps ✓ | 25/30 |
| Total | — | 130/150 |
Steps to reproduce
- Configure with
evaluateEnabled: true - POST to
/actwith body:{kind: "evaluate", fn: "document.cookie"} - Observe arbitrary JavaScript execution in the browser context
Expected behavior
Even when evaluate is enabled, there should be:
- Sandboxing or scope restrictions
- Input validation against known-safe patterns
- Audit logging of evaluated code
- Rate limiting
Actual behavior
The fnText parameter is passed directly to eval() with no restrictions:
Affected code location:
Evaluate Implementation (src/browser/pw-tools-core.interactions.ts:227-257):
const browserEvaluator = new Function(
"fnBody",
`
"use strict";
try {
var candidate = eval("(" + fnBody + ")");
return typeof candidate === "function" ? candidate() : candidate;
} catch (err) {
// ...
}
`
);Environment
- Version: latest (main branch)
- OS: Any
- Install method: Any
Impact
- Session hijacking: Read cookies, localStorage, sessionStorage
- Credential theft: Capture form inputs, access saved passwords
- Data exfiltration: Read page content, make authenticated requests
- Malware delivery: Inject scripts, redirect users
- Lateral movement: Access internal network resources via browser
Recommended fix
- Remove evaluate functionality entirely, or
- Implement a strict allowlist of safe operations:
const ALLOWED_EVALUATIONS = {
'getInnerText': (selector: string) => document.querySelector(selector)?.innerText,
'getValue': (selector: string) => (document.querySelector(selector) as HTMLInputElement)?.value,
// ... other specific, safe operations
};
// Reject arbitrary code, only allow predefined operations
if (!ALLOWED_EVALUATIONS[operation]) {
throw new Error(`Unsupported evaluation: ${operation}`);
}