#6000: fix(browser): add CORS headers for chrome-extension:// origins
Cluster:
Chrome Extension Enhancements
## Summary
Fixes #5856
The extension relay server was missing CORS headers, causing the Chrome extension's preflight `fetch()` check to fail.
## Root Cause
The HTTP server handlers didn't set any CORS headers for `chrome-extension://` origins:
```javascript
if (req.method === "HEAD" && path === "/") {
res.writeHead(200); // No CORS headers
res.end();
return;
}
```
## Changes
- Add `getCorsHeaders()` helper to detect `chrome-extension://` and `moz-extension://` origins
- Handle `OPTIONS` preflight requests with 204 response
- Include CORS headers in all HTTP responses when origin matches
- Add test case for CORS header behavior
## Testing
- Added new test: "returns CORS headers for chrome-extension:// origins"
- All 4 extension-relay tests pass
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds CORS handling to the extension relay HTTP server by detecting `chrome-extension://` and `moz-extension://` origins, responding to `OPTIONS` preflight requests with 204, and attaching CORS headers to all relevant HTTP responses. It also adds a Vitest case to validate that extension origins receive the expected CORS headers.
The change fits into the relay’s local HTTP control plane (`/`, `/json/*`, `/extension/status`), ensuring the Chrome extension can perform fetch() preflights against the relay without being blocked by missing CORS headers.
<h3>Confidence Score: 4/5</h3>
- This PR is likely safe to merge; the main remaining risk is incomplete preflight header handling for non-trivial requests.
- Changes are localized to HTTP response headers and include a new test; however, the preflight handler currently allows only `Content-Type`, which may not cover the extension’s actual requested headers and could leave the original issue partially unfixed in some environments.
- src/browser/extension-relay.ts (preflight/header handling), src/browser/extension-relay.test.ts (coverage for requested headers).
<!-- greptile_other_comments_section -->
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#16060: fix(browser): require relay auth token for /extension WebSocket and...
by coygeek · 2026-02-14
76.8%
#5278: fix(browser): prevent DNS rebinding in extension relay HTTP endpoints
by webvijayi · 2026-01-31
73.9%
#10937: fix(browser): correct fallback path for bundled Chrome extension
by dddabtc · 2026-02-07
73.5%
#22252: fix(chrome-extension): connection validation and clarify relay port...
by krizpoon · 2026-02-20
72.7%
#21314: feat: enhance browser relay with custom naming and diagnostic tools
by kelvinCB · 2026-02-19
72.1%
#9796: fix(cli): correct fallback path for bundled Chrome extension (#9772)
by lailoo · 2026-02-05
72.0%
#20688: fix(browser): allow extension reconnect when stale websocket linger...
by HOYALIM · 2026-02-19
71.8%
#19766: fix: Chrome relay extension auto-reattach after SPA navigation
by nishantkabra77 · 2026-02-18
71.5%
#16689: browser: support multiple Chrome extension connections to relay
by globalcaos · 2026-02-15
71.4%
#14944: fix(browser): prefer openclaw profile in headless/noSandbox environ...
by BenediktSchackenberg · 2026-02-12
71.4%