Browser tool
A real headless browser the agent can drive — but only against hosts you've explicitly allowlisted. Default deny.
Why an allowlist
The browser tool is powerful: full Playwright-class navigation, JavaScript execution, screenshot capture, form interaction. That power is also a liability — a compromised model that's allowed to fetch arbitrary URLs can exfiltrate secrets or attack internal services.
So: default deny. The browser cannot reach any host until you say so.
How to open the allowlist editor
- Keyboard:
Ctrl+Shift+B(Windows/Linux) or⌘⇧B(Mac). - Top bar chip: Browser.
The first time you open it, the status row reads:
> Default deny — no host is reachable.
That's correct. You need to add hosts.
Adding hosts
Type a host pattern in the input. Patterns:
| Pattern | Matches |
|---|---|
example.com | Exact host (no subdomains). |
*.example.com | Any subdomain (e.g. api.example.com, cdn.example.com). |
* | Everything. Floodgates open. Confirm-guarded. |
There's a hard cap of 256 host rules per workspace.
Presets
Three quick-fill chips:
- localhost — loopback addresses + common dev ports (5173, 5060, 3000, 8000).
- preview — your current Vercel/Netlify/Pages.dev preview hosts.
- floodgates —
*. Use only for throwaway workspaces.
Pre-flight gating
Every browser request — browser.smoke, browser.marketing, browser.flow — is gated:
- The base URL is checked against the allowlist.
- Every
gotostep within a flow is checked again.
Failure mode: HTTP 403 with default-deny: <host> in the body. The agent sees this and reports it.
Backend test
curl -X POST -H "Content-Type: application/json" \
-d '{"url":"https://example.com"}' \
https://your-workspace.krowforge.com/browser/smoke
If example.com isn't allowlisted: 403 with reason default-deny:example.com. Add example.com in the allowlist UI, retry, and you'll get a 200.
Audit trail
Every change to the allowlist is logged with the actor and the diff:
audit browser.allowlist.set user=42 added=[example.com] removed=[]
You can review the audit log in the workspace settings.
What gets stored
Each workspace has its own allowlist file under the cache dir, written atomically (.tmp → replace). It's per-workspace — sharing a workspace with a teammate shares the allowlist.