BrowserBox Documentation

06 Make it yours

Customer Policy Surface

Customer guide · v20.8.5 · November 12, 2026

In this chapter

6.1 What policy controls #

BrowserBox policy is the customer-facing runtime control surface that answers two distinct questions:

  • Which sensitive actions are allowed or denied?

  • Which browsing targets may the remote browser reach?

The canonical persisted policy file lives at:

~/.config/dosaygo/bbpro/policy/policy.json

BrowserBox normalizes and validates that file before applying it. If a field is omitted, BrowserBox fills in safe defaults for the current schema.

The allowed values listed in this section are based on BrowserBox’s current runtime validation and normalization surface, not on a separate aspirational specification. In practice, customers should be able to trust this section because these values are the same ones BrowserBox validates at load time.

6.2 Canonical policy fields #

The customer-relevant policy bundle currently includes these high-level surfaces:

Field Meaning
transport.certificateErrors Whether BrowserBox enforces certificate validation or explicitly allows self-signed / invalid certificates.
navigation.mode Top-level navigation mode: open, allowlist, or blocklist.
navigation.allowlist Allowed navigation targets when navigation.mode=allowlist. Supports exact host, exact origin, exact URL, and wildcard host patterns (§6.5.2).
navigation.blocklist Denied navigation targets when navigation.mode=blocklist.
navigation.internalAllowlist Exact browser-internal origins that may open. It defaults to empty. chrome://inspect and the other permanently reserved targets cannot be enabled.
navigation.privateNetwork.mode Whether private/local targets are denied by default or controlled through an allowlist.
navigation.privateNetwork.allowlist Explicit private/local destinations that may be reached, including exact hosts, IPs, and IPv4 CIDRs.
featureControls.copy Controls copy actions, including modifier shortcuts and context-menu copy paths.
featureControls.paste Controls paste actions, including text insertion into the remote browser.
featureControls.downloads Controls download routes and archive-serving surfaces. When set to deny, the download is cancelled at the browser level before any data is written to disk, and the connected client receives a policy-denied notification.
featureControls.uploads Controls upload routes and file input surfaces.
featureControls.devtools Controls DevTools access.
featureControls.audio Controls the audio sidecar service.
featureControls.automation Controls the BrowserBox automation surface used by the webview API.
featureControls.contextMenu Controls whether the remote-page context menu may open.
featureControls.browserChrome Whether BrowserBox’s tab bar and address bar are shown, hidden or user-toggleable. always-hide keeps them hidden whatever the login link, the address bar or an embedder asks for (§6.7).

6.3 Allowed values and defaults #

The most important values customers need to know are listed here directly.

6.3.1 Binary feature controls #

Unless stated otherwise, feature controls are binary decisions:

Field Allowed values Default / note
featureControls.copy allow, deny Required in the persisted policy bundle.
featureControls.paste allow, deny Required in the persisted policy bundle.
featureControls.downloads allow, deny Required in the persisted policy bundle.
featureControls.uploads allow, deny Required in the persisted policy bundle.
featureControls.devtools allow, deny Required in the persisted policy bundle.
featureControls.audio allow, deny Required in the persisted policy bundle.
featureControls.automation allow, deny Required in the persisted policy bundle.
featureControls.contextMenu allow, deny If omitted, BrowserBox currently defaults this field to allow for backward compatibility.

6.3.2 Enumerated policy fields #

Field Allowed values Default / note
transport.certificateErrors enforce, ignore-all Defaults to enforce.
navigation.mode open, allowlist, blocklist Required in the persisted policy bundle.
navigation.privateNetwork.mode deny, allowlist Defaults to deny.
featureControls.browserChrome toggle, api, always-show, always-hide Defaults to toggle. Use always-hide for kiosks (§6.8).

6.3.3 Identity and access configuration #

Three fields govern identity integration for authenticated BrowserBox deployments:

Field Allowed values Note
identity.authMode magic-link, sso-saml How users authenticate. magic-link uses email-based one-time links; sso-saml routes through an IdP.
identity.ssoProvider none, okta, entra, custom The IdP in use when authMode=sso-saml. Use custom for non-enumerated providers.
identity.peerCapabilityModel shared, scoped Whether multiple connected clients in the same session share capabilities (shared) or each client has its own scoped capability set (scoped).

6.3.4 List-valued policy fields #

Field Allowed entry form
navigation.allowlist Array of non-empty strings. Entries may be exact hosts, exact origins, exact URLs, or wildcard host patterns; see §6.5.2 for how each matches.
navigation.blocklist Array of non-empty strings. Entries follow the same matching forms as the navigation allowlist.
navigation.internalAllowlist Array of exact, origin-only chrome://page or chrome-extension://<32-character-id> strings. Wildcards, paths, queries and fragments are rejected. An allowed extension origin covers paths within that exact extension.
navigation.privateNetwork.allowlist Array of non-empty strings. Entries may be exact hosts, exact IPs, or IPv4 CIDRs.

6.3.5 Where customers can verify allowed values #

Customers do not have to guess. BrowserBox exposes the current policy surface through the customer-facing policy CLI:

  • bbx policy show --scope global|user prints one persisted policy source.

  • bbx policy show prints the normalized effective policy that BrowserBox is actually using.

  • bbx policy validate --file policy.json validates a candidate policy file against the current code and reports invalid enum values directly.

For example, if a customer uses an unsupported mode, BrowserBox validation reports the current accepted set, such as:

featureControls.browserChrome must be one of:
toggle, api, always-show, always-hide

6.4 Sensitive actions BrowserBox can allow or deny #

These actions currently route through BrowserBox’s policy authorization layer:

Action Customer-visible effect
navigate Page navigation, history navigation, new-tab target creation, and clean-slate navigation flows.
uploads File upload routes and file chooser / file input flows.
downloads Download and archive-serving routes. When denied, the download is cancelled before any data reaches the server’s download directory, and the user sees a policy-denied notification in the BrowserBox client UI.
devtools BrowserBox DevTools service and its websocket bridge.
audio BrowserBox audio service.
copy Keyboard and context-menu copy paths.
paste Keyboard and API-driven paste / insert-text paths.
automation The automation methods exposed through the webview API, such as selector waits, clicks, typing, and evaluation.
contextmenu The remote-page context menu UI.

All of these controls are binary allow / deny decisions except featureControls.browserChrome, which uses explicit UI visibility modes described below.

6.5 Navigation, browser-internal and private-network policy #

BrowserBox separates ordinary browsing, browser-internal access and private/local reachability:

  • navigation.allowlist answers “where may the RBI tab browse?”

  • navigation.internalAllowlist answers “which explicitly named browser-internal origins may open?”

  • navigation.privateNetwork.allowlist answers “which private or local destinations may any request reach?”

  • ALLOWED_EMBEDDING_ORIGINS is separate and only controls which parent pages may embed BrowserBox

Browser-internal navigation is denied by default, independently of navigation.mode. To permit an internal page, add its exact origin, for example chrome://extensions. To permit an extension’s pages, add the exact extension origin, for example chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; BrowserBox then permits paths within that extension. chrome://inspect, chrome://newtab, chrome://omnibox-popup, and devtools:// remain forbidden even if listed. If global and user policies are both active, both must list the origin. about:blank is structurally accepted so BrowserBox can stage safe tab creation, but a user-requested blank tab still follows the configured navigation mode.

The BrowserBox Extensions button is shown only when the effective internal allowlist contains chrome://extensions or a valid exact extension origin. This visibility check uses the policy snapshot only; it does not scan the installed extensions directory.

Mode Behavior
open Any ordinary browsing target is allowed, subject to the separate private-network and browser-internal boundaries.
allowlist Only configured allowlist entries may be reached.
blocklist All targets are allowed except those matching the configured blocklist.

6.5.2 How allowlist entries match #

Allowlist and blocklist entries take four forms. The form of the entry decides how it matches:

Entry Form Matches Does not match
*.example.com Wildcard host example.com itself and every subdomain at any depth, such as www.example.com and a.b.example.com. Any scheme, port and path. notexample.com, example.org
www.example.com Exact host www.example.com on any scheme, port and path. example.com, a.www.example.com
https://app.example.com Exact origin Any path on that scheme, host and port. A trailing / makes no difference. The same host over http://, or on port 8443
https://example.com/a?b=1 Exact URL That path and query only. A #fragment is ignored. /a, /a/c?b=1, /a?b=2

Avoid these mistakes:

  • A path without a scheme allows the whole site. An entry such as example.com/maps or example.com/maps/* is read as the host example.com. To allow only certain pages, list each page as an exact URL, scheme included. There are no path-prefix entries.

  • Only a leading *. is a wildcard. An entry such as *example.com or www.*.example.com is read as a literal host name and matches nothing.

  • bbx policy validate does not flag either mistake. Before you rely on an entry, test the addresses you mean to allow and refuse:

    bbx policy check --action navigate --url https://www.example.com/
  • Every page load is checked, including links, redirects and new windows opened from an allowed page. If a site sends users through another host, such as a sign-in or media host, that host needs its own entry.

The page a user reaches when a navigation is denied can be replaced with your own; see §5.8.

6.5.3 Private-network controls #

Private-network policy defaults to deny. Customer policy may widen that boundary explicitly:

Field Meaning
mode=deny Denies private and local targets such as RFC1918 addresses, localhost, and the unspecified addresses 0.0.0.0 and :: by default.
mode=allowlist Keeps the private/local boundary in place but permits explicit entries.
allowlist entries Exact hosts, exact IPs, and IPv4 CIDRs, for example 10.0.0.5, 10.0.0.0/8, and localhost.

IPv4-mapped IPv6 addresses such as ::ffff:10.0.0.5 are classified as the IPv4 address they carry, so they cannot be used to bypass an IPv4 rule. An allowlist entry containing / must be a valid IPv4 CIDR; an invalid or IPv6 CIDR is ignored rather than treated as a host. Run bbx policy validate after editing the allowlist and bbx policy check --action navigate --url <url> to confirm the result for a specific destination.

6.6 Certificate-error policy #

Certificate handling is now policy-driven rather than hidden behind a permanent launch flag.

Mode Behavior
enforce Default. BrowserBox enforces certificate validation and will not silently accept certificate errors.
ignore-all Explicit opt-in for environments that need to reach self-signed or otherwise invalid HTTPS targets.

6.7 Browser chrome policy modes #

featureControls.browserChrome does not allow or deny a risky action. Instead, it governs whether BrowserBox’s own visible browser chrome, the tab bar and address bar, is shown, hidden, or user-toggleable.

Mode Visible UI User toggle Meaning
toggle visible by default yes Legacy-compatible mode. The login link’s ui= sets the starting state. The user may show or hide BrowserBox chrome unless the embedder locks it.
api visible by default no The embedder may drive UI visibility through the API, but the end user may not toggle it directly.
always-show always visible no BrowserBox chrome must remain visible.
always-hide always hidden no BrowserBox chrome stays hidden for kiosk-style or tightly embedded experiences. A ui=true login link, an edited address bar, the context menu and the embedder API cannot show it. For a kiosk, combine it with a navigation allowlist (§6.8).

If the embedder sets ui-visible or allow-user-toggle-ui, those values may further restrict the experience. They cannot widen what the server policy allows.

Navigation in always-hide mode: when chrome is hidden, BrowserBox’s built-in back/forward buttons are not visible to the user. However, tab history is preserved internally. Embedders can navigate the remote browser’s history programmatically through the webview API:

await webview.callApi('goBack');
await webview.callApi('goForward');

The remote-page context menu has no back option. Embedders that need end-user back navigation in always-hide mode should add their own back button wired to the goBack API call above.

6.8 Locking kiosk mode #

A kiosk that users must not leave needs two settings in the server policy. The user’s browser cannot override either of them.

  • featureControls.browserChrome set to always-hide. The chrome stays hidden: a ui=true login link, an edited address bar, the context menu and the webview API cannot show it.

  • A navigation allowlist naming the kiosk’s sites (§6.5). The server refuses every page load outside it: typed addresses, new tabs, and links, redirects and new windows opened from inside an allowed site.

The allowlist is the boundary; always-hide removes the controls. Hiding the chrome alone is not a boundary, because a user who modifies the browser client could show it again. The allowlist still limits that user to the listed sites, so always set both.

Set them in the global policy, /etc/browserbox/policy.json. The global browserChrome setting takes precedence over a per-user policy, and the global policy applies to every BrowserBox Fleet seat on the host.

# If there is no global policy yet:
sudo bbx policy init --scope global --baseline regulated
sudo cp /etc/browserbox/policy.json kiosk.json
# In kiosk.json set:
#   "featureControls": { ..., "browserChrome": "always-hide" }
#   "navigation": { "mode": "allowlist", "allowlist": ["www.example.org"], ... }
sudo bbx policy set --scope global --file kiosk.json

New sessions start with the policy. In always-hide mode a user who follows a link off the allowlist has no back button, so install a blocked-policy.html page (§5.8.2) with a link back to the kiosk’s start page.

6.9 Per-destination feature controls #

featureControls settings such as downloads and paste are currently global — the same setting applies to all browsing destinations regardless of which site the user is on. Different featureControls per allowlist entry are not supported. If your use case requires different download or clipboard behavior on different sites, the recommended approach is to run separate BrowserBox instances each with a distinct policy configuration.

6.10 Server policy versus embedder policy #

BrowserBox has three relevant policy layers:

  1. Global server policy, stored in /etc/browserbox/policy.json, which applies to every Unix user and Fleet seat.

  2. User server policy, stored in the user’s existing BrowserBox policy directory, which may tighten but never loosen the global policy.

  3. Embedder policy hints, supplied through the canonical webview surface, which may only restrict and never widen the effective server policy.

  • An action is allowed only when every active server-policy scope allows it.

  • With no global policy, the user policy behaves exactly as before.

  • User and embedder restrictions may narrow capabilities further.

  • An embedder cannot override a server-side deny into an allow.

6.11 Customer policy CLI #

BrowserBox ships a policy CLI so customers can inspect, initialize, validate, and test the effective policy surface.

bbx policy help
bbx policy where [--scope global|user] [--json]
bbx policy baselines
bbx policy controls [--json]
bbx policy show [--scope global|user]
bbx policy get [--scope global|user]
bbx policy resolve
bbx policy check --action <name> [--url <https://...>] [--source <tag>]
bbx policy trace [--last <n>]
bbx policy init [--scope global|user] [--baseline regulated|compat]
bbx policy reset [--scope global|user] [--baseline regulated|compat]
bbx policy set [--scope global|user] --file <path/to/policy.json>
bbx policy validate [--scope global|user] [--file <path/to/policy.json>]

6.11.1 Useful commands #

Command Meaning
bbx policy where Prints the resolved Unix principal plus global and user policy paths and status.
bbx policy baselines Lists supported baseline names.
bbx policy controls –json Prints the documented NIST 800-53 and FIPS 140 control surfaces.
bbx policy show Prints the effective policy actually enforced, with source and principal diagnostics.
bbx policy show –scope global Prints the raw stored global policy; use --scope user for the user’s raw policy.
bbx policy resolve Compatibility alias for the compiled / normalized effective policy snapshot.
bbx policy check –action ... Evaluates a single action decision. Exit code 0 means allow; exit code 2 means deny.
bbx policy trace –last 20 Shows recent policy decisions from the decision trace log.
bbx policy init –scope user –baseline compat Creates the selected scope from a named baseline.
bbx policy reset –scope global –baseline regulated Replaces the selected scope with a named baseline.
bbx policy set –scope user –file policy.json Loads, validates, and atomically persists a policy at the selected scope.
bbx policy validate Validates the current persisted policy or an explicitly supplied file.

6.11.2 Recipe: global policy with a per-user tightening #

Set the administrator-owned policy that applies to every BrowserBox Unix user and Fleet seat:

bbx policy set --scope global --file global-policy.json

Optionally set a stricter policy for one Unix user. The operator reads the source file and BrowserBox writes it in the target user’s policy store, so the target account does not need access to the operator’s file:

bbx policy set --scope user --file policy.json --for user-bbx-0901

Inspect the effective policy actually enforced for that user, then inspect the raw user layer if needed:

bbx policy show --for user-bbx-0901
bbx policy show --scope user --for user-bbx-0901
bbx policy where --for user-bbx-0901

The user layer may tighten the global policy but cannot weaken it. Reset only that user’s layer to a named baseline with:

bbx policy reset --scope user --baseline compat --for user-bbx-0901

6.12 Operational visibility #

When policy blocks an action, BrowserBox emits both customer-visible and operator-visible signals:

  • a policy-denied notification in the client UI when a connected client is present at the time of the block

  • server log entries prefixed with [policy-decision]

  • a persistent trace file at /̃.config/dosaygo/bbpro/policy/decisions.ndjson

Actions that currently produce client-visible notifications include:

Action Notification trigger
navigate A navigation to a blocked destination.
downloads A browser download that was cancelled before any bytes reached disk.
copy, paste, devtools, uploads, automation, contextmenu The corresponding action was attempted while denied by policy.
tab-limit A new tab or popup was blocked because the session is at the configured tab cap (BBX_MAX_TABS).

Tab-limit blocks that occur during service startup are silent—they close excess tabs without showing a client notification, since no client is connected yet.

BrowserBox · Published by DOSAYGOHappy browsing.