A browser under AI control visits hostile pages. We build for that.
These are the controls that apply to every run, on every plan. They are design rules, not settings, and most of them are covered by tests in our own suite.
Secrets never enter a prompt
The agent emits {{secret:login_password}}. The runner substitutes the value at keystroke time, inside the browser driver, only on origins the environment allows. Prompts, observations, logs, traces, exports and recorded steps carry the placeholder, never the value. Observations are scrubbed against every secret value before the model or the UI sees them.
Page content is data, never instructions
Everything read from the page is wrapped as untrusted content with a system-level statement that it describes what to test and is never a command. Prompt injection through the app under test is the defining risk for browser agents; we assume every page attempts it.
A constrained action space
The model can only emit typed actions against a validated schema: navigate, click, type, select, scroll, wait, assert, extract, hand off, done. No free-form code, no arbitrary URLs. Navigation targets must be on the environment's allowlist.
Human approval for dangerous verbs
Payments, deletions, sending messages, irreversible controls and navigation off the allowlist pause the run and wait for a person. The classifier is deterministic and a denial is recorded as a skipped step the model is told about.
Masking at capture
Password, card and identifier-shaped fields are masked when frames and recordings are captured, not redacted later. Vision is disabled on any step that carries a secret, so a vision model cannot read a credential off the screen.
Isolated browser sessions
Each session gets its own browser context, and on plain servers its own transient, hardened Chrome process: dynamic user, read-only system, private temp and devices, no new privileges, outbound network limited to the environment's addresses. It is destroyed when the session ends.
Egress guard for user-supplied URLs
Provider base URLs and integration endpoints are resolved by us, checked against loopback, private, link-local and mapped ranges on every request, never follow redirects, and are capped in time and size.
Keys in a secret store, not the database
Model keys, environment secrets and integration tokens are written to a file-backed secret store with restrictive permissions. Database rows keep only a reference. Prompts, DOM snapshots, video and traces live in object storage with a pointer row.
One broker, one connection
Neither the agent nor the viewer ever opens a connection to the browser. A single broker owns it, arbitrates control with an epoch-stamped lease, and rejects any command from a stale epoch.
Accounts and tenancy
Accounts use email and password with a memory-hard hash. Sessions are server-side rows behind a signed, HttpOnly cookie and are confirmed with the control plane on every request, so sign-out, member removal and password resets take effect in every open browser immediately. Every tenant-scoped table is protected by row-level security and the application connects as a role that cannot bypass it.
Local models
Local models are served by a small runner next to the model. It makes an outbound HTTPS connection to Handoff, receives prompts, calls the model on localhost and returns completions. No inbound firewall rule, no public hostname, no tunnel. Prompts and page snapshots for those bindings never leave your network.
Model providers and data retention
Because Handoff runs on your key, your provider's data handling terms apply to your prompts. Bindings record a retention note and an “allowed in production” flag; evaluation-only endpoints can be blocked from CI-triggered cycles.
Reporting a vulnerability
Write to info@avancezone.com with steps to reproduce. We acknowledge reports within two business days and keep you informed until the issue is resolved. Please do not test against other customers' organisations.