fix: reflect CORS for chrome-extension origins so Side Panel fetches succeed#1550
Open
Bmathews721 wants to merge 1 commit into
Open
fix: reflect CORS for chrome-extension origins so Side Panel fetches succeed#1550Bmathews721 wants to merge 1 commit into
Bmathews721 wants to merge 1 commit into
Conversation
…succeed The Side Panel runs in a chrome-extension:// origin and fetches /health, /command, /refs, /activity/stream, and the terminal-agent's /claude-available with credentials:'include'. None of those responses set Access-Control-Allow-Origin or Access-Control-Allow-Credentials, so every fetch fails CORS and the panel never reaches the connected state — the bootstrap card stays stuck on "Browse server not ready" and the install-card shows "Claude Code not found" even when claude is on PATH. Repro: launch `browse connect`, open the Side Panel from a fresh extension load, watch DevTools console fire "Access to fetch at 'http://127.0.0.1:34567/health' from origin 'chrome-extension://...' has been blocked by CORS policy". Fix: * server.ts — add a `withCors` middleware (preflight OPTIONS 204 + response-header reflection) and wrap both makeFetchHandler call sites. Reflects the Origin header back ONLY when it starts with chrome-extension://, so arbitrary websites still get no CORS headers. Sets Access-Control-Allow-Credentials: true to satisfy credentials:'include' on the panel's fetches and EventSource(..., {withCredentials:true}). * terminal-agent.ts — add the same Origin + Credentials headers to the /claude-available response. WS upgrade keeps Sec-WebSocket-Protocol auth and doesn't need CORS; /internal/* stays loopback + bearer-auth. * server-auth.test.ts, terminal-agent.test.ts — source-pattern tests matching the existing /refs and /activity/history CORS-test style. Verify the middleware exists, gates on chrome-extension://, sets both headers, and is never wildcarded. Verification curl (post-patch): $ curl -H "Origin: chrome-extension://abc" -D - http://127.0.0.1:34567/health HTTP/1.1 200 OK Access-Control-Allow-Origin: chrome-extension://abc Access-Control-Allow-Credentials: true $ curl -H "Origin: https://evil.com" -D - http://127.0.0.1:34567/health HTTP/1.1 200 OK (no Access-Control-* headers — non-extension origins still blocked) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
c17f88d to
e268718
Compare
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
/health,/command,/refs,/activity/stream, and terminal-agent's/claude-availablewere failing CORS because none of those responses setAccess-Control-Allow-OriginorAccess-Control-Allow-Credentials. Panel stays stuck on "Browse server not ready" and the install-card shows "Claude Code not found" even whenclaudeis on PATH.withCorsmiddleware inserver.tsthat wraps bothmakeFetchHandlercall sites — preflightOPTIONS204 + response-header reflection, only for origins starting withchrome-extension://. Arbitrary websites still get no CORS headers./claude-available. The/wsupgrade keepsSec-WebSocket-Protocolauth and doesn't need CORS;/internal/*stays loopback + bearer-auth./refs has no wildcard CORS headerstyle inserver-auth.test.ts.Repro before fix
After the panel is reloaded, the next blocker surfaces:
Verification curl
Test plan
bun test browse/test/server-auth.test.ts browse/test/terminal-agent.test.ts— 3 new tests pass; pre-existing failures unrelated (markers forSidebar agent startedetc.)Security notes
Originwhen it starts withchrome-extension://. Never wildcards. Arbitrary websites can't read these endpoints' responses./healthtoken exposure is unchanged (still gated on headed-mode or chrome-extension origin per the existing logic)./wsupgrade in terminal-agent is unchanged — still requiresSec-WebSocket-Protocolauth + extension Origin check./internal/grantand/internal/revokestill loopback + Bearer; CORS doesn't apply.🤖 Generated with Claude Code