ruvnet/ruflo · error · Error

browser/eval: script contains disallowed pattern: ${pattern.

Error message

browser/eval: script contains disallowed pattern: ${pattern.source}

What it means

Thrown by browser/eval when the script matches any regex in DANGEROUS_EVAL_PATTERNS. The blocklist includes: process, require, __dirname, __filename, child_process, global. (with dot), globalThis, Function(, .constructor, Reflect, import(, and eval(. The thrown message echoes the offending pattern.source so you can see which rule fired. This is a defense-in-depth layer, explicitly noted as bypassable — the browser sandbox is the real boundary.

Source

Thrown at v3/@claude-flow/browser/src/mcp-tools/browser-tools.ts:677

        },
      },
      required: ['script'],
    },
    handler: async (input) => {
      const script = input.script as string;

      // Validate script length
      if (!script || script.length === 0) {
        throw new Error('browser/eval: script must not be empty');
      }
      if (script.length > MAX_EVAL_SCRIPT_LENGTH) {
        throw new Error(`browser/eval: script exceeds maximum length of ${MAX_EVAL_SCRIPT_LENGTH} characters`);
      }

      // Check for dangerous patterns
      for (const pattern of DANGEROUS_EVAL_PATTERNS) {
        if (pattern.test(script)) {
          throw new Error(`browser/eval: script contains disallowed pattern: ${pattern.source}`);
        }
      }

      // Audit log
      console.info(`[browser/eval] Executing script (${script.length} chars) in session ${input.session || 'default'}`);

      const adapter = getAdapter(input.session as string);
      return adapter.eval({ script });
    },
  },
];

// ============================================================================
// Storage Tools
// ============================================================================

const storageTools: MCPTool[] = [
  {

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Rewrite the script to avoid the blocked token (e.g., use 'window' instead of 'globalThis', avoid 'process' entirely).
  2. Strip Node-specific code before sending — the eval runs in the page context, not Node.
  3. If a blocked token is unavoidable and the script is trusted, move the logic into a page-loaded module invoked by a thin eval wrapper.

Example fix

// before
await evalTool.handler({ script: 'globalThis.myVal = 42;' }); // throws 64 (globalThis)

// after
await evalTool.handler({ script: 'window.myVal = 42;' });
Defensive patterns

Strategy: validation

Validate before calling

const BLOCKED = [/\bprocess\b/, /\brequire\b/, /\b__dirname\b/, /\b__filename\b/, /\bchild_process\b/, /\bglobal\b\s\./, /\bglobalThis\b/, /\bFunction\s*\(/, /\.constructor\b/, /\bReflect\b/, /\bimport\s*\(/, /\beval\s*\(/];
function isSafeScript(script) {
  return typeof script === 'string' && !BLOCKED.some(p => p.test(script));
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Any eval script that contains one of the blocked substrings as a literal or via a regex match, including innocent uses like the word 'process' in a comment, a webpack require shim, or accessing globalThis for a polyfill.

Common situations: LLM-generated scripts that reference Node globals; reusing Node-targeted code in the page; bundlers that emit require() calls; accessing window via globalThis.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/5da204444322c0e5. Report an issue: GitHub.