SafetyCard Request a review

Steel Browser

Open-source, self-hostable browser API (REST, WebSocket and Chrome DevTools) for AI agents and automation.

github.com/steel-dev/steel-browser · 2026-10-04 · e5902fc

Defense-in-depth score

2.4 / 10

Steel Browser gives whoever drives it full control of a browser that holds logged-in sessions, and the network exposure and access control of its REST API and Chrome DevTools port in the shipped configuration are not locked down. Inside the root-run container, Chrome's own sandbox and site isolation are switched off, and the API will load Chrome extensions from arbitrary paths. Only run it on a private network behind your own authenticating proxy.

Safest setup

Steel Browser keeps network request bodies and typed values out of its logs and records requests and browser events, but the network exposure and access control of its API in the shipped configuration are not locked down, nothing asks before a browser action, and Chrome runs without its own sandbox. With few protections to turn on, the safest setup narrows what the browser is logged into and builds the boundaries around the container yourself.

SetupHowWhat it gives you
Low-privilege site accountsLog the browser in only to the accounts the task needs, using dedicated low-privilege accounts where the site offers themWhoever drives the browser can act only as those accounts, not as every account you use C1
A private, authenticated entryReach the API and DevTools port only over a private network, through your own proxy that requires authenticationOnly callers you have authenticated can drive the browser and its logged-in sessions C1
Bundled extensions onlyHave your client request extensions only by name in extensions, from the set bundled in the imageThe browser runs only extension code that shipped with the image C7
A hardened containerRun the container with dropped capabilities, no-new-privileges, memory and CPU limits, and outbound access limited to the sites the task needsAn outer boundary around page code running in a browser whose own sandbox is off C4
A fresh container per taskRecreate the container for each task or user, with no browser profile kept on a volumeCookies and site data planted during one task don't carry into the next C6
Sessions with an endHave your client release each session when its task finishes, and recreate the container on a fixed scheduleNo browser session keeps running after the work it was started for C10
A kept event logKeep the shipped LOG_STORAGE_ENABLED=true and copy the log volume regularly to storage the API can't reachA record of API requests and browser events that outlives anything an API client does to it C9

Approving with confidence

  • Steel has no confirmation step of its own, so gate form submissions, purchases and posts in the agent host: read each prompt and approve calls one at a time.

Handling data

  • Cookies the browser holds are long-lived logins; treat the browser profile and the session material the API returns like the passwords of those accounts.
  • The stored event log records the URLs of every navigation and request; store it like browsing history.

Key gaps (1)

  1. Untrusted web content driving or reaching the browser can exfiltrate data and take irreversible logged-in actions with no human involved. C5 · Untrusted input blast radius

Criteria

C1 Identity & least privilege

0.05 / 1.00

Steel Browser has no per-caller identity or separation between callers: whoever drives it gets full control of the single shared browser, including every logged-in website session it holds. Access control on its HTTP, WebSocket and Chrome DevTools endpoints in the shipped configuration is not locked down.

C2 Approval gates

0.00 / 1.00

As a tool server, Steel Browser does not give the host anything to gate on: endpoints carry no read-only or destructive hints, there is no dry-run, and the raw Chrome DevTools connection mixes reading and every possible browser action in one channel. Any irreversible action on a website (submitting forms, purchases, posts) is one CDP call away with no server-side confirmation.

C3 Tool & action scoping

0.23 / 1.00

Request bodies are typed with Zod schemas and the file API checks that resolved paths stay inside its base directory, and named extensions are matched against a bundled directory. But URLs are passed straight to the browser and to a server-side fetch that follows redirects, with no block on localhost or cloud metadata addresses, and the session API accepts arbitrary extension paths and Chrome preferences. The full CDP channel is on by default, so the effective tool is 'do anything a browser can do'.

C4 Code-execution isolation

0.57 / 1.00

Chromium executes untrusted page JavaScript and caller-supplied scripts via CDP inside the shipped Docker container. That container runs as root with no hardening, and because it runs as root the code automatically disables Chrome's own sandbox and also turns off site isolation. Chrome's environment is scrubbed to a few variables, but the container has unrestricted network access and a read-write bind mount of the host's ./.cache directory.

C5 Untrusted input blast radius

0.25 / 1.00

Steel Browser's whole job is to load untrusted web pages for an agent. Scrape output separates content from metadata and records the source URL, but nothing marks content as untrusted or offers a read-only or no-egress mode. If an agent driving it is hijacked by page content, it can browse anywhere, use logged-in cookies, and submit forms with no server-side check.

C6 Memory, context & configuration integrity

0.00 / 1.00

Steel has no AI memory store or instruction files, but the browser profile is its persistence: by default every session reuses the same Chrome user-data directory and nothing clears cookies or site storage between sessions or callers. Anything a malicious page plants (cookies, local storage, service workers) can carry into later sessions for any caller of the shared server. Uploaded files are cleaned on shutdown.

C7 Third-party extensions

0.20 / 1.00

Chrome extensions are the extension surface. Named extensions are restricted to a directory bundled in the image, which by default holds only Steel's own recorder. However, the session API also accepts arbitrary filesystem paths through extra.orgExtensions.paths and loads them with no integrity check. Such an extension runs in the root-owned, unsandboxed browser with access to all sites.

C8 Secrets & sensitive-data protection

0.45 / 1.00

Network header and body logging is off by default, the interaction recorder omits typed values and flags password fields, and no telemetry exporter is configured. But API responses expose sensitive session material. Browser cookies are long-lived account sessions.

C9 Audit & traceability

0.33 / 1.00

Every API request is logged with client IP, URL, method and status, and the browser instrumentation records navigations, network and console events, which compose persists to a DuckDB file. Individual CDP commands sent by a client are not recorded as such, there is no caller identity beyond IP, and the stored logs are not protected from the clients they record. Writes are buffered and flushed every two seconds.

C10 Limits & kill switch

0.33 / 1.00

Navigation in the action endpoints times out after 30 seconds, request bodies are capped at 100 MB and file storage per session at 100 MB, and releasing a session kills the Chrome process. But sessions have no timeout by default, the KILL_TIMEOUT setting is never read, delays are unbounded, and there are no rate limits despite the architecture docs claiming them.