fix(security): disable browser.evaluateEnabled by default

BREAKING CHANGE: browser.evaluateEnabled now defaults to false.

The evaluate feature allows arbitrary JavaScript execution in the browser
context via the /act endpoint (kind=evaluate) and wait --fn. This is a
powerful escape hatch for advanced automation but poses security risks:

- Prompt injection: LLM agents can be tricked into running malicious code
- Network exposure: If gateway is accessible, attackers can exfiltrate data
- Session hijacking: Code runs with access to cookies, localStorage, DOM

With this change:
- act:evaluate and wait --fn return 403 by default
- Users who need this feature can enable it explicitly:
  browser.evaluateEnabled: true

Built-in actions (click, type, screenshot, wait for text/URL, etc.) remain
fully functional and cover the vast majority of automation use cases.
This commit is contained in:
Nir Zadok 2026-01-29 13:03:08 +02:00
parent 01e0d3a320
commit ad7cd8f44d
6 changed files with 7 additions and 7 deletions

View File

@ -2769,7 +2769,7 @@ scheme/host for profiles that only set `cdpPort`.
Defaults: Defaults:
- enabled: `true` - enabled: `true`
- evaluateEnabled: `true` (set `false` to disable `act:evaluate` and `wait --fn`) - evaluateEnabled: `false` (set `true` to enable `act:evaluate` and `wait --fn`; disabled by default for security)
- control service: loopback only (port derived from `gateway.port`, default `18791`) - control service: loopback only (port derived from `gateway.port`, default `18791`)
- CDP URL: `http://127.0.0.1:18792` (control service + 1, legacy single-profile) - CDP URL: `http://127.0.0.1:18792` (control service + 1, legacy single-profile)
- profile color: `#FF4500` (lobster-orange) - profile color: `#FF4500` (lobster-orange)
@ -2780,7 +2780,7 @@ Defaults:
{ {
browser: { browser: {
enabled: true, enabled: true,
evaluateEnabled: true, evaluateEnabled: false,
// cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override // cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override
defaultProfile: "chrome", defaultProfile: "chrome",
profiles: { profiles: {

View File

@ -507,7 +507,7 @@ These are useful for “make the site behave like X” workflows:
- The clawd browser profile may contain logged-in sessions; treat it as sensitive. - The clawd browser profile may contain logged-in sessions; treat it as sensitive.
- `browser act kind=evaluate` / `moltbot browser evaluate` and `wait --fn` - `browser act kind=evaluate` / `moltbot browser evaluate` and `wait --fn`
execute arbitrary JavaScript in the page context. Prompt injection can steer execute arbitrary JavaScript in the page context. Prompt injection can steer
this. Disable it with `browser.evaluateEnabled=false` if you do not need it. this. **Disabled by default for security.** Enable with `browser.evaluateEnabled: true` if needed.
- For logins and anti-bot notes (X/Twitter, etc.), see [Browser login + X/Twitter posting](/tools/browser-login). - For logins and anti-bot notes (X/Twitter, etc.), see [Browser login + X/Twitter posting](/tools/browser-login).
- Keep the Gateway/node host private (loopback or tailnet-only). - Keep the Gateway/node host private (loopback or tailnet-only).
- Remote CDP endpoints are powerful; tunnel and protect them. - Remote CDP endpoints are powerful; tunnel and protect them.

View File

@ -6,7 +6,7 @@ import type { SkillEligibilityContext, SkillEntry } from "./types.js";
const DEFAULT_CONFIG_VALUES: Record<string, boolean> = { const DEFAULT_CONFIG_VALUES: Record<string, boolean> = {
"browser.enabled": true, "browser.enabled": true,
"browser.evaluateEnabled": true, "browser.evaluateEnabled": false,
}; };
function isTruthy(value: unknown): boolean { function isTruthy(value: unknown): boolean {

View File

@ -1,5 +1,5 @@
export const DEFAULT_CLAWD_BROWSER_ENABLED = true; export const DEFAULT_CLAWD_BROWSER_ENABLED = true;
export const DEFAULT_BROWSER_EVALUATE_ENABLED = true; export const DEFAULT_BROWSER_EVALUATE_ENABLED = false;
export const DEFAULT_CLAWD_BROWSER_COLOR = "#FF4500"; export const DEFAULT_CLAWD_BROWSER_COLOR = "#FF4500";
export const DEFAULT_CLAWD_BROWSER_PROFILE_NAME = "clawd"; export const DEFAULT_CLAWD_BROWSER_PROFILE_NAME = "clawd";
export const DEFAULT_BROWSER_DEFAULT_PROFILE_NAME = "chrome"; export const DEFAULT_BROWSER_DEFAULT_PROFILE_NAME = "chrome";

View File

@ -14,7 +14,7 @@ export type BrowserSnapshotDefaults = {
}; };
export type BrowserConfig = { export type BrowserConfig = {
enabled?: boolean; enabled?: boolean;
/** If false, disable browser act:evaluate (arbitrary JS). Default: true */ /** If true, enable browser act:evaluate (arbitrary JS). Default: false (disabled for security) */
evaluateEnabled?: boolean; evaluateEnabled?: boolean;
/** Base URL of the CDP endpoint (for remote browsers). Default: loopback CDP on the derived port. */ /** Base URL of the CDP endpoint (for remote browsers). Default: loopback CDP on the derived port. */
cdpUrl?: string; cdpUrl?: string;

View File

@ -6,7 +6,7 @@ import type { HookEligibilityContext, HookEntry } from "./types.js";
const DEFAULT_CONFIG_VALUES: Record<string, boolean> = { const DEFAULT_CONFIG_VALUES: Record<string, boolean> = {
"browser.enabled": true, "browser.enabled": true,
"browser.evaluateEnabled": true, "browser.evaluateEnabled": false,
"workspace.dir": true, "workspace.dir": true,
}; };