fix: restrict daemon CORS to trusted origins (CWE-942)#108
Open
sebastiondev wants to merge 1 commit intosteipete:mainfrom
Open
fix: restrict daemon CORS to trusted origins (CWE-942)#108sebastiondev wants to merge 1 commit intosteipete:mainfrom
sebastiondev wants to merge 1 commit intosteipete:mainfrom
Conversation
- Add isTrustedOrigin() allowlist for browser-extension and localhost origins - Reject arbitrary web origins in corsHeaders() to prevent cross-site probing CWE-942: Permissive Cross-domain Policy with Untrusted Domains
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
The daemon's CORS policy reflects any
Originheader back verbatim together withAccess-Control-Allow-Credentials: trueandAccess-Control-Allow-Private-Network: true. This allows arbitrary websites to issue cross-origin requests to the daemon running on localhost, bypassing the browser's same-origin restrictions that normally protect local services.Root cause:
corsHeaders()never validates the incoming origin before echoing it into the response.Affected Code
corsHeaders()src/daemon/server.tsOriginwithout validationresolveOriginHeader()src/daemon/server.tsImpact
Unauthenticated fingerprinting — any website a user visits can silently probe
GET /health(unauthenticated) and learn that the daemon is running, its exact version, and its PID. This is useful for reconnaissance.Private Network Access bypass — the
Access-Control-Allow-Private-Network: trueheader tells Chrome to allow the cross-origin request to a private/localhost address even from a secure (HTTPS) page. Without origin validation this effectively opts the daemon out of Chrome's PNA protections.Credential relay if token is compromised — because
Access-Control-Allow-Credentials: trueis set for every origin, a malicious page that has obtained the bearer token (e.g. from a leaked config file, log, or shoulder-surfing) can make fully authenticated requests to/v1/summarize,/v1/agent, etc. from the user's browser session.Proof of Concept
A page on any origin can fingerprint the daemon:
The browser allows this because the daemon responds with:
Fix
Adds an
isTrustedOrigin()allowlist check before reflecting the origin:chrome-extension://,moz-extension://,safari-web-extension://schemes are allowed (the daemon's primary cross-origin consumer is the Chrome/Firefox extension).localhost,127.0.0.1,[::1]hostnames are allowed (local dev tooling).The change is a single guard added to
corsHeaders()plus the new helper; no other code paths are affected. Existing tests pass.