Repository navigation
fix(browser): CDP addresses through a TLS-ending tunnel are https and wss (FD-5470) - #608
Merged
Merged
Conversation
… wss (FD-5470) browser/v1 cdp takes an optional origin, where the caller's agent reaches the env, and mints the address under it; discovery under such a token answers the WebSocket it minted. browser_connect_cdp names the env's URL as the agent's sandbox reaches it, when the browser's card takes an origin. Behind Modal's tunnel, which ends TLS and adds no X-Forwarded-Proto, the browser could only see http, so agents got http and ws addresses that were refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An origin named HTTPS://... passed the check but its WebSocket form came out as ws://HTTPS://...; the origin is now rebuilt from its parsed parts, scheme in lower case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale
added a commit
that referenced
this pull request
Nov 11, 2026
…gin the agent's named, on containers too browser_connect_cdp names the agent's origin on the cdp call it asks through the multi env's gateway too, as #608 has it name it of a browser asked directly, and the gateway keeps the https or wss of an address the browser minted under it. So behind a tunnel that ends TLS, as Modal's, the address and its discovery are https and wss on a VM and on Modal containers alike, where a container gateway's tunnel URL isn't known until it runs. The deploy no longer tells the gateway its gateway_url (AGENTENV_GATEWAY_URL), which only a VM deploy could. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part of M8.58 (FD-5470). On a remote provider whose tunnel ends TLS,
browser_connect_cdphanded agentshttp://andws://CDP addresses for a host that only answershttpsandwsson 443, so their connections were refused. Now the step names where the agent reaches the env, and the browser builds the address under that origin, the way a deploy already builds an env's MCP and site URLs outside the VM.Why it happened: Modal's tunnel ends TLS and opens a plain HTTP connection to the VM, adding no
X-Forwarded-Proto(probed on amodal_vmtunnel). The driver tells the browser the scheme of the connection it accepted, which is http, so the browser mintedhttp/wsaddresses, and discovery (json/version) answeredws.browser_connect_cdprebases only an address that starts with the env's URL, scheme included, so it couldn't repair it. Local Docker never shows it: the caller and the driver both see http.What changes
browser/v1 cdp(agentenv_protocol.website_browser)origin: an http or https URL, a path allowed, with no query, fragment or credentials; anything else is refused as an invalid argument before anything is minted./cdp/<token>/. The token store keeps that it was named so, by hash as before.origin, both answer at the address the request reached, as before.browser_connect_cdporigin, when the browser's card listsoriginoncdp. A browser composed before this refuses a parameter it doesn't know, so it's asked as before and its answer rebased as before._rebasedstays: a gateway's CDP answers, which it rewrites to the address the step reached it at, still need it.The token file gains
named, read as required: no caller produces a file without it. It's written and read only by the browser's own app server, beside its socket, no snapshot carries it, a computer never changes image while it runs, and a data reset revokes every token.Not in this PR: the gateway's CDP route (
browser_proxy.public_base) and its site routes'X-Forwarded-Proto(rest_proxy.forwarded_address) fall back to the connection's scheme the same way, so behind such a tunnel they'd say http too. A follow-up.Decisions (in chat with Edgar)
http_urlconnects to whateverjson/versionnames, so the browser keeps the named address for it.Test plan
test_browser_cdp.pymints under a named origin over a request that arrived over http and checks discovery answerswss; refuses ten bad origins without minting; keeps the named flag through a restart; the card listsorigin.test_browser_connect_cdp.pysends the agent's origin for a browser onmodal_vmand on local Docker, and none to a browser whose card doesn't take one. The protocol package,tst/unit/task_stepandtst/unit/env/gateway: 4,802 passed, 1 skipped.test_behind_a_front_that_ends_tls_..., with a front ending TLS in front of the browser computer (tst/util/tls_front.py, the local CA's certificate) as a remote provider's tunnel does: the address named under the front's origin ishttps/wss, discovery answerswss, and Playwright byhttp_url, Puppeteer byws_urland Playwright byws_urlopen the site through it; asked without an origin, it'swsthere. The CDP clients andbrowser_connect_cdptests beside it, andbrowser_gateway_test.py, pass.modal_vm: the browser computer composed on a Modal builder from this branch and probed there (gate 3 ready). Its addresses through Modal's tunnel: named,https/wss, withjson/versionansweringwss, and all three clients connect; unnamed,http/ws. Browser Use (Claude Sonnet 5.5) on two Online-Mind2Web tasks, each recorded: on Apple it added the cheapest blue 256GB certified refurbished iPad Air to the bag ($669, the bag page in the recording's last frames); CarMax answered every page load from Modal's network withERR_HTTP2_PROTOCOL_ERROR, as the recording shows, though the CDP connection worked.Docs
The user guide's browser page should say that
browser/v1 cdptakes an optionalorigin, where the caller's agent reaches the env, whichbrowser_connect_cdppasses, and that addresses and discovery are then https and wss through a tunnel that ends TLS.🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; no blocking issue remains.Summary
The PR lets callers name the origin used for CDP addresses and discovery, so clients get
httpsandwssthrough tunnels that end TLS.Diagram
Reviews (6) · Last reviewed commit: "fix(browser): an origin's scheme is read..." · Reviewed by Greptile