Skip to content

fix(server): match browser extension CORS origins exactly - #850

Open
eachann1024 wants to merge 1 commit into
lidge-jun:devfrom
eachann1024:fix/browser-extension-cors-origin
Open

fix(server): match browser extension CORS origins exactly#850
eachann1024 wants to merge 1 commit into
lidge-jun:devfrom
eachann1024:fix/browser-extension-cors-origin

Conversation

@eachann1024

@eachann1024 eachann1024 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

What changed

  • canonicalize authority-based opaque origins as scheme + authority instead of the WHATWG null serialization
  • allow only the configured browser extension ID while keeping other extensions and * rejected
  • cover both preflight and /v1/models data-plane requests
  • document browser-extension origins in the English and Simplified Chinese configuration references

Why

URL.origin serializes chrome-extension://... URLs as null. Comparing that value made every browser extension look identical, while rejecting a wildcard configuration still left users without a safe way to allow one extension to call the local data plane.

Change graph

flowchart LR
    Request["Browser extension request"] --> Parse["Parse request origin"]
    Allowlist["corsAllowOrigins"] --> Match["Exact origin matcher"]
    Parse --> Standard["Standard HTTP(S) origin"]
    Parse --> Opaque["Opaque authority origin"]
    Standard --> Match
    Opaque --> Authority["Compare scheme + authority"]
    Authority --> Match
    Match --> Decision{"Allowlisted?"}
    Decision -->|Yes| DataPlane["OpenCodeX data plane"]
    Decision -->|No| Rejected["403 origin_rejected"]
Loading

Checks

  • bun test tests/server-loopback-host-gate.test.ts tests/server-auth.test.ts tests/management-origin-tls.test.ts (76 passed)
  • bun run typecheck
  • bun run lint:gui
  • bun run privacy:scan
  • cd docs-site && bun run build
  • isolated real-server smoke: configured extension OPTIONS /v1/models = 204, GET /v1/models = 200, different extension = 403 origin_rejected
  • full suite: 6504 passed, 4 skipped, 7 failed; the same 7 failures reproduce on clean upstream/dev because local Fake-IP DNS resolves .test / .invalid fixtures into 198.18.0.0/15 and the destination policy rejects them (tests/provider-outbound.test.ts, tests/management-provider-validation.test.ts)

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features

    • CORS allowlists now support browser extension origins such as chrome-extension://<extension-id>.
    • Configured extension origins are accepted for preflight and model requests, while unconfigured origins remain blocked.
  • Documentation

    • Updated English and Chinese configuration guidance to clarify exact-origin matching and that * is not a wildcard.

@github-actions github-actions Bot added the bug Something isn't working label Aug 1, 2026
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

CORS allowlist matching now supports configured browser extension origins through canonical scheme-and-authority comparison. Tests cover Chrome extension access and rejection cases. Type and reference documentation describe exact-origin behavior and clarify that * is not a wildcard.

Changes

Browser Extension CORS Origins

Layer / File(s) Summary
Canonical origin matching
src/server/auth-cors.ts, src/types.ts
isExtraAllowedOrigin parses origins once and compares canonical values. Opaque custom-scheme origins use scheme and authority matching. Noncanonical values use exact-string fallback. The configuration type documentation describes HTTPS and chrome-extension:// origins.
Integration coverage and reference documentation
tests/server-auth.test.ts, tests/server-loopback-host-gate.test.ts, docs-site/src/content/docs/reference/configuration.md, docs-site/src/content/docs/zh-cn/reference/configuration.md
Tests verify configured Chrome extension origins for preflight and /v1/models, reject unconfigured and Firefox extension origins, and reject wildcard-only configuration. English and Chinese references document the same behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: lidge-jun, wibias, ingwannu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: exact matching for browser extension CORS origins.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/reference/configuration.md`:
- Line 73: Update the corsAllowOrigins documentation rows in the Japanese,
Korean, and Russian localized pages to match the English description: state that
authority-based browser extension origins such as
chrome-extension://<extension-id> are supported and that * is not a wildcard,
while preserving the existing configuration details.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4302c78e-3c2b-4608-bf78-fba4afa2469f

📥 Commits

Reviewing files that changed from the base of the PR and between e1fc0f2 and 58fef36.

📒 Files selected for processing (6)
  • docs-site/src/content/docs/reference/configuration.md
  • docs-site/src/content/docs/zh-cn/reference/configuration.md
  • src/server/auth-cors.ts
  • src/types.ts
  • tests/server-auth.test.ts
  • tests/server-loopback-host-gate.test.ts

| `images?` | `OcxImagesConfig` | automatic OpenAI selection | Standalone Images relay options for Codex's built-in `image_gen` tool (see below). |
| `tokenGuardian?` | `OcxTokenGuardianConfig` | off | Optional proactive OAuth refresh and Codex-account warmup policy; fields are listed below. |
| `corsAllowOrigins?` | `string[]` | `[]` | Additional exact origins allowed by CORS. Loopback origins are always allowed. |
| `corsAllowOrigins?` | `string[]` | `[]` | Additional exact origins allowed by CORS. Loopback origins are always allowed. Authority-based browser extension origins such as `chrome-extension://<extension-id>` are supported; `*` is not a wildcard. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -i '^configuration\.md$' docs-site/src/content/docs | sort
rg -n -C 2 'corsAllowOrigins|chrome-extension|not a wildcard|不是通配符' \
  docs-site/src/content/docs

Repository: lidge-jun/opencodex

Length of output: 6108


Sync localized CORS documentation

Update the corsAllowOrigins rows in the Japanese (line 66), Korean (line 67), and Russian (line 71) pages. State that chrome-extension://<extension-id> origins are supported and * is not a wildcard.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs-site/src/content/docs/reference/configuration.md` at line 73, Update the
corsAllowOrigins documentation rows in the Japanese, Korean, and Russian
localized pages to match the English description: state that authority-based
browser extension origins such as chrome-extension://<extension-id> are
supported and that * is not a wildcard, while preserving the existing
configuration details.

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant