Context
The /api/git-proxy/[...path] route was hardened on 2026-05-30 to add isOriginAllowed + checkRateLimit guards on every GET / POST (see SECURITY.md audit log). The CORS preflight handler OPTIONS still echoes a permissive Access-Control-Allow-Origin: * regardless of the calling origin. The actual GET / POST handler will refuse a cross-origin request, so the headline risk is closed — but the preflight currently advertises that ANY origin would be accepted, which is misleading and a defense-in-depth gap.
This issue is a small, scoped, fully-self-contained hardening that mirrors the pattern already used by the real handler.
Where to look
src/app/api/git-proxy/[...path]/route.ts lines 105-115 — the OPTIONS export.
- Same file lines 40-55 — the existing
isOriginAllowed + checkRateLimit pattern in handle().
src/utils/originAllowlist.ts — the allowlist logic; returns { ok, origin } | { ok: false, reason }.
Acceptance criteria
Complexity
Small.
For first-time contributors
Read CONTRIBUTING.md and SECURITY.md (the audit-log section explains the prior hardening). npm install, npm test, PR against dev.
Context
The
/api/git-proxy/[...path]route was hardened on 2026-05-30 to addisOriginAllowed+checkRateLimitguards on every GET / POST (see SECURITY.md audit log). The CORS preflight handlerOPTIONSstill echoes a permissiveAccess-Control-Allow-Origin: *regardless of the calling origin. The actual GET / POST handler will refuse a cross-origin request, so the headline risk is closed — but the preflight currently advertises that ANY origin would be accepted, which is misleading and a defense-in-depth gap.This issue is a small, scoped, fully-self-contained hardening that mirrors the pattern already used by the real handler.
Where to look
src/app/api/git-proxy/[...path]/route.tslines 105-115 — theOPTIONSexport.isOriginAllowed+checkRateLimitpattern inhandle().src/utils/originAllowlist.ts— the allowlist logic; returns{ ok, origin } | { ok: false, reason }.Acceptance criteria
OPTIONSreads the requestOriginheader.isOriginAllowed(request).ok === true: respond204withAccess-Control-Allow-Origin: <origin>(echoing the allowed origin, NOT*) plus aVary: Originheader.403with no CORS headers (the browser will then block the request).src/__tests__/covers both branches with mockedRequestobjects.Complexity
Small.
For first-time contributors
Read
CONTRIBUTING.mdandSECURITY.md(the audit-log section explains the prior hardening).npm install,npm test, PR againstdev.