Implementation Guide

    How to Block JavaScript Evaluation in Browser Automation MCP Servers

    Remove or hide every tool that runs caller-supplied script in a live page, then enforce the same decision on each tool call at runtime and test for equivalent paths through other tools and arguments. Server configuration removes the capability, a client allowlist limits what the agent can see, and runtime policy enforcement blocks and records attempts. No single layer covers all three jobs.

    Step 4: Verify that the block holds at runtime

    • Request the tool list from the agent's view and confirm the evaluate-style tools are absent.
    • Call each blocked tool directly and confirm the call is refused and no script runs.
    • Attempt equivalent behavior through allowed tools, including URL schemes and script-registering tools.
    • Place a harmless injected instruction in a test page and confirm the agent cannot turn it into script execution.
    • Send code-like strings in the arguments of navigation, click and type calls and confirm policy decisions match expectations.
    • Confirm every attempt above produced a retrievable record, including the refused ones.

    Why JavaScript evaluation tools carry elevated risk

    Most browser automation tools expose fixed verbs: navigate, click, type, take a snapshot. Each has a narrow, predictable effect. A JavaScript evaluation tool is different because the caller supplies the code, and that code runs in the context of the live page. Whatever script on that page can do, the supplied code can do, including reading page content and making requests with the authority of the signed-in session.

    Browser protections still apply. NIST describes the same-origin policy as stopping content from one origin from getting or setting properties of a document from a different origin. That protection does not help when the injected code runs inside the origin you are trying to protect. An authenticated page and its data sit inside the boundary the script operates in.

    The path to misuse does not need a malicious operator. A NIST CSRC presentation on agentic AI security notes that untrusted inputs or poisoned context can cause an agent to generate harmful commands that run in legitimate automation environments. A browser agent reads web content by design, so it ingests untrusted input continuously. A mistaken instruction from a user or a prompt injection in a page can become code execution through one tool call, bypassing the constraints you placed on navigation, click and type.

    Step 1: Identify which tools expose the capability

    Start with an inventory of each browser automation MCP server you run, taken from its live tool listing and the documentation for the exact version deployed. Classify tools by behavior, not by name. An evaluate tool is easy to spot. A tool described as running a snippet, a function or a script may be the same capability under a different label.

    • List every tool and its input schema: Capture names, descriptions and parameters for each server and version in use.
    • Flag tools that accept code: Look for parameters that take a script string, a function body or an expression to run in the page.
    • Flag indirect script paths: Consider tools that inject script tags, register scripts to run on page load, or alter requests and responses.
    • Check general-purpose escape hatches: Note tools that run arbitrary commands or code in the server process, since these can reach the browser by other means.
    • Record the result per version: Store the classification with the server version and repeat it on every upgrade, because tool sets change.

    Step 2: Choose and combine blocking layers

    The three layers sit at different points and make different guarantees. Treat them as complementary. NIST's allowlisting guidance favors permitting known-good activity and blocking everything else, which argues for an explicit list of approved tools over a list of banned names.

    • Server configuration or tool removal: Sits at the source. If the tool is never registered, it cannot be called by any client. Does not stop equivalent behavior through other tools, depends on the server offering a way to disable the tool, and must be rechecked after upgrades. Applies only to servers you control.
    • Client or host allowlist: Sits where the agent discovers tools. Restricts the agent to approved tools and fits default-deny. Coverage depends on each client, and each client needs separate configuration. It usually works at tool-name level and does not inspect arguments.
    • Runtime policy on tool calls: Sits in the execution path between agent and server. Can evaluate the tool name and arguments for every call, apply one policy across clients and servers, and produce a record of each decision. Needs ongoing policy maintenance and must sit on every route the agent can use.

    Step 3: Close bypass paths and decide on exceptions

    Blocking a tool name is coarse. NIST notes that some controls can only permit or block a whole class of scripts, while others work on individual scripts. The same gap exists here. A name-level block stops the obvious tool, but code can reach the page through other routes, such as a navigation tool given a javascript: URL, depending on how the server handles it, or a tool that registers scripts to run on load. Argument inspection at runtime addresses these cases by examining what is being passed, not only which tool is called.

    NIST's Cage and Filter patterns are a useful way to reason about this. Cage constrains what code can do while it runs. Filter examines code at an entry point and blocks it if it is judged harmful. Removing the tool at the server resembles caging the capability. Inspecting calls in the execution path resembles filtering. Using both gives you depth.

    Expect usability costs. NIST has cautioned that blocking active content can break many sites, and the same holds for automation workflows that rely on page scripting. Define exceptions deliberately: scope them to internal or trusted targets, require human approval, and assign an owner to the allowlist. An exception that nobody owns becomes a permanent hole.

    Evidence to retain and where runtime enforcement fits

    An auditor wants to see that script execution was disallowed at runtime and that attempts were recorded, not only that a setting exists. For each blocked or escalated call, retain the tool name, the arguments as submitted (redacted where they contain sensitive data), the policy decision and the rule that produced it, the timestamp, and the identity of the agent, client and user session. Keep the test plan, results and server versions alongside these records, and set a retention period that matches your obligations.

    Trussed enforces policy in the execution path for tool calls across agents, tools, MCP servers and coding assistants. It can allow, redact, block, rate limit or escalate a call for human approval, and the decisions are enforced at runtime, not reviewed after the fact. Each enforced decision produces audit-ready evidence, and deployment is self-managed in the customer cloud with configurable retention and data residency. This is the runtime layer described above. It complements, and does not replace, removing the tool at the server and allowlisting at the client.

    Three layers for blocking script execution

    Server

    Disable or remove the evaluate-style tool so it is never offered.

    Client or host

    Allowlist approved tools so unlisted tools are not callable by the agent.

    Runtime policy

    Decide on each tool call, including its arguments, and record the outcome.

    Enforce and evidence tool-call policy

    See how policy on MCP tool calls is enforced in the execution path and how each blocked call becomes audit-ready evidence.

    See How Evidence Is Produced