Skip to content

Policy format ​

Policies are live for new sessions. Sessions created before enforcement report unsupported and remain unrestricted, even after sleep and wake. Create a replacement session to use a policy on that work.

A session has one policy. It is asked about every mcp.callTool that code in run_js makes, and every JavaScript fetch() request. A call it does not allow is refused, and the code gets an error. If the policy cannot be asked, the call is refused.

A policy is written in Rego. A new session can start from a ready-made one (unrestricted, browser only, no scripting, observe only, one site, form filling, read-only shell) and edit it.

Rego ​

One module in Rego v1 syntax, at most 65536 bytes.

  • It declares package computeruse.policy. The name is fixed, and carries the product's earlier name.
  • It defines allow_tool_call. A call is allowed only when that is true.

The input for each call:

FieldValue
input.operation"mcp_call_tool"
input.serverThe capability's server: "browser", or "exec" for the shell
input.toolThe tool: "browser_execute" or "desktop_execute" on browser; "exec", "stream_logs", "search_logs" or "kill" on exec
input.argumentsThe arguments as the code passed them. Not validated first: any field can be missing or of any type

A call to a server or tool not listed here is refused whatever the policy says.

A call no rule allows is refused, so a policy that only speaks of browser_execute refuses desktop control, the shell, and fetch.

Nothing in the input says which user or client is calling.

Arguments of each tool ​

ServerToolinput.arguments
browserbrowser_execute{ operations: [{ type, params }] }. Types: navigate, click, type, press, select, wait, screenshot, setViewport, url, evaluate, setContent
browserdesktop_execute{ operations: [{ type, params }] }. Types such as mouse.click, keyboard.type, keyboard.pressKey, screen.grab, clipboard.getContent
execexec{ bin, args, timeout, cwd, env }: a program run directly, with no shell. args, cwd and env are optional; timeout is in seconds
execstream_logs, search_logs, kill{ id, ... }: read or stop a command that was started. They start nothing

For exec, compare bin as a whole string ("git" and "/usr/bin/git" are different), check args one by one, bound timeout, and refuse env and cwd unless a rule checks them: env can set PATH, which changes what a program name runs. A list of programs is a list of entry points, not a sandbox. An allowed program can start others.

Fetch requests ​

Fetch requests use the same allow_tool_call rule with a separate input:

FieldValue
input.operation"fetch"
input.urlThe requested URL
input.methodHTTP method such as "GET" or "POST"
input.headersRequest headers, including any headers supplied by the server
input.url_parsed{ scheme, host, port, path, query }; port is null when not explicit

Fetch inputs have no server, tool, or arguments. For example, add this rule to a browser policy to allow only HTTPS GET requests to one API path:

rego
allow_tool_call if {
    input.operation == "fetch"
    input.url_parsed.scheme == "https"
    input.url_parsed.host == "api.example.com"
    startswith(input.url_parsed.path, "/v1/")
    input.method == "GET"
}

Use Test in the policy editor to try the GET, POST, and other-host samples, then save and wait for the policy to be in force. Subsequent requests use the new rules without a session restart.

All requests are denied unless an allow rule matches. Unrestricted (allow_tool_call := true) permits all HTTP(S) fetch requests. Every other preset denies fetch until a rule is added. To allow any HTTP(S) request, add allow_tool_call if input.operation == "fetch". To deny fetch, remove all rules that can allow it, including an unrestricted rule; a false rule does not override an allow rule because Rego combines allow rules with OR. allow_fetch is not an entry rule.

Pod network restrictions still apply. These rules govern fetch() in run_js; browser navigation, page scripts, module downloads, and shell programs have their own controls and can also contact hosts.

Ready-made policies ​

PolicyBrowserDesktopShell
Unrestricted (the default)EverythingEverythingEverything
Browser onlyEverythingRefusedRefused
No scriptingEverything except running script in a page or replacing its contentRefusedRefused
Observe onlyOpen https pages, wait, take screenshotsRefusedRefused
One siteOne site and its subdomains, short typed textRefusedRefused
Form fillingThe sites you name, printable text, a few keysRefusedRefused
Read-only shellEverythingRefusedpwd, ls, cat on files below the home folder, git status, log, diff, show; 60 seconds at most

Warnings when saving ​

The tools are not independent, so some policies restrict less than they appear to. Saving one of these succeeds with a warning.

WarningThe policy
browser_bypass_desktopRestricts the browser but lets the desktop click or type. The mouse and keyboard reach the address bar and DevTools
browser_bypass_shellRestricts the browser but lets exec run arbitrary programs. A program can call the browser's control ports inside the session
shell_bypass_desktopRestricts exec but lets the desktop click or type. The keyboard can type any command into a terminal
shell_launcher_allowedLists programs but allows sh, bash, env or xargs, each of which runs any other program
shell_env_allowedLists programs but lets a call set PATH

The warnings come from trying a few calls against the policy. They catch the common mistakes, not every one.

Where it is kept ​

ModeEdited
In the appIn the editor on the session's Policy tab
As codeThrough the API or the Terraform provider. The app shows it read-only

A new session with no policy given gets the unrestricted one. It stays starting until its first policy is in force. Saving an edit can return while it is still loading; the previous policy remains in force until the new one is loaded. An invalid edit also leaves the previous policy in force.