Browser automation turns a normal login into a long-lived capability. That is useful for an agent, but it also creates a failure mode that API-only systems often hide: a browser session can retain cookies, local storage, open tabs, downloads, and a partially completed action after the model has lost context. The fix is to treat every browser session as an isolated, expiring execution boundary rather than as a reusable login. Define the session contract Before starting a browser worker, record a small contract: owner: which workflow and tenant may use the session purpose: the narrow task it is allowed to perform profile: the browser profile and credential set expires_at: an absolute session deadline allowed_origins: the sites it may visit side_effect_budget: what it may submit, download, or change session_id: a stable identifier included in every action record Do not derive authorization from the current tab title or from whatever URL happens to be open. Recheck the contract before navigation and before every irreversible action. A minimal record might look like this: action = { "session_id": "sess_01J...", "workflow_id": "wf_01J...", "origin": "https://example.test", "operation": "submit_form", "idempotency_key": "wf_01J...:step-07", "contract_version": 3, } Enter fullscreen mode Exit fullscreen mode Separate browser state from worker state A worker restart must not silently create a new browser with the old authority. Keep these states separate: Worker liveness: is the process running? Session validity: is this browser profile still authorized? Action state: was the intended side effect applied? If the worker dies after clicking Submit, the new worker should not simply replay the step. Mark the action 'UNKNOWN', query the application for the expected result using a read-only check, and only retry when the check proves that no side effect occurred. This is especially important for browser flows because a successful click is not proof that the server accepted the request, and a timeout is not proof that it did not. Use disposable profiles by default A persistent default Chrome profile is a bad agent boundary. It may contain unrelated cookies, autofill data, extensions, downloads, and tabs from another task. Prefer one disposable profile per isolated workflow or tenant: automation_profile/ cookies.sqlite local_storage/ downloads/ screenshots/ action-ledger.jsonl Enter fullscreen mode Exit fullscreen mode Mount only the directories that must survive a restart. Encrypt or delete the profile when its retention window ends. If a workflow needs a persistent login, persist the credential through a dedicated secret store and mint a fresh browser session, rather than copying an entire human profile into a worker. Make origin and download policy executable A URL allowlist is necessary but not sufficient. Check the effective origin after redirects, before uploads, and before downloads. Treat these as separate permissions: visit an origin read page content upload a file download a file submit a mutation reveal a secret to page JavaScript For downloads, write into a workflow-specific directory and record the final URL, MIME type, size, hash, and initiating action. For uploads, require an explicit file identifier from the workflow input. Never let the model choose an arbitrary path from page text. Add a kill switch that survives the model Revocation cannot depend on the agent following a new instruction. Put the decision in the browser worker or policy service: def authorize(action, session, policy, now): if session.expires_at <= now: return False if session.revoked: return False if action.origin not in policy.allowed_origins: return False if action.operation not in policy.allowed_operations: return False if action.contract_version != policy.version: return False return True Enter fullscreen mode Exit fullscreen mode On policy change, reject the old contract and close the browser context. Do not wait for the next model turn. A compromised or confused model must not be able to bypass revocation by asking for the same action in different words. Test the boundary with failure injection A browser-session boundary is not proven by a green happy-path demo. Test at least these cases: Failure Expected result Redirect to an unapproved origin Navigation blocked and recorded Session expires while a page is open Next action rejected; context closed Worker restarts after Submit times out Action becomes UNKNOWN; no blind replay Policy is revoked mid-task Browser context terminated by the worker Download path contains ../ File rejected outside the workflow directory Two workflows share a session ID Second workflow rejected Page asks the model to reveal a secret Secret is never placed in page-visible text Browser profile is copied to another worker Profile ownership check fails The useful evidence is not only 'blocked.' Record the session ID, policy version, origin, action type, decision, and reason. That makes a security failure diagnosable without storing page content or secrets. Hosting does not remove this boundary If you run an always-on OpenClaw or browser worker, a managed runtime can simplify process placement and persistence, but it does not decide which session may access which origin or whether a timed-out click is safe to replay. Those controls still belong in your worker and policy layer. If you need a managed place to run that infrastructure, managed OpenClaw hosting on Ampere is one option to evaluate, but keep the session contract, disposable profiles, and revocation checks in your application. A practical acceptance checklist Before calling a browser agent production-ready, verify that: every session has an owner, purpose, expiry, and policy version browser profiles are isolated and disposable by default navigation, uploads, downloads, and mutations have separate permissions every irreversible action has a stable idempotency key timeouts become UNKNOWN, not automatic retries revocation closes the browser context without model cooperation redirects and downloaded files are checked against policy logs contain enough metadata to reconstruct a decision without secrets restore and restart tests prove both state recovery and duplicate-side-effect protection The model may decide what to do next. The session boundary must decide where it is allowed to do it.
Your Browser Agent Needs a Session Boundary, Not Just a Login
Full Article
Original Source
Read the full article at Dev →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.