fix(extension-ingest): restrict credentialed CORS to the app's own hosts - #68
Conversation
Co-authored-by: polylane[bot] <277585245+polylane[bot]@users.noreply.github.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Tip Expected to resolve the linked issue. Linked issue: iss_0c23c2a9800103uy2zijkxul — any *.cachd.app origin can read a user's extension ingest token (docs.cachd.app is third-party hosted) The token endpoint's only callers fetch it same-origin from Also considered · 2 refuted
Analysed against 1 Project and 1 repository
Polylane analysed Did this help? React 👍 or 👎 so the next review is sharper. |
Fixes: cache-app: any *.cachd.app origin can read a user's extension ingest token (docs.cachd.app is third-party hosted)
The endpoint that returns a user's extension ingest token granted credentialed cross-origin access to any single-label subdomain of cachd.app. Because docs.cachd.app and preview.cachd.app are served by third parties, a page on one of them could make a credentialed request to the app and read the signed-in user's ingest token, which permits writing library items into that account. Only the app's own hosts now receive that response.
What caused this
Affected:
acc_0b563dc42001x121b0ek7bgcWhy this fix
The credentialed CORS decision was a wildcard over cachd.app labels:
TRUSTED_CACHE_WEB_ORIGIN_PATTERNSmatched any[a-z0-9-]+subdomain, andextensionTokenCorsHeadersechoed it withAccess-Control-Allow-Credentials: true. The zone's wildcard DNS and cert make every label resolve and TLS-valid, and two are delegated to third parties today (docsCNAME to Mintlify returns 200;previewCNAME to unkey-dns.com). Unassigned labels do not serve the app (test/api probes returned 404), so the allowlist was wider than the hosts the app actually serves.The fix replaces the label wildcard with an explicit first-party origin set (
https://cachd.app,https://www.cachd.app, plus localhost for development). The extension reads the token fromwindow.location.originand posts ingest items from the extension's own origin, so only the app's hosts and chrome-extension origins need to be in the allowlist; the check for chrome-extension origins is unchanged.docs.cachd.app,preview.cachd.app, and any other delegated label now receive no allow-origin header, so the browser blocks the response read.The origin policy moved into
lib/integrations/extension-ingest/origins.tsso the decision is a pure, testable unit; the CORS header construction stays in the route. The regression test asserts the two app hosts and localhost are accepted, and that the third-party and unassigned subdomains and lookalikes are rejected.The extension's own
*.cachd.appmatch patterns are a separate client-side trust assumption and are left unchanged; they are not the credentialed read path and cannot produce the token from a third-party origin.3 files changed (+82/-18)
lib/integrations/extension-ingest/origins.test.ts: added, +50/-0lib/integrations/extension-ingest/origins.ts: added, +27/-0lib/integrations/extension-ingest/route.ts: modified, +5/-18Generated by Polylane. You can ask follow-ups by mentioning @polylane in a comment.