fix: stop echoing all request headers in CORS response headers#241
Open
Alice39s wants to merge 1 commit intotiagozip:mainfrom
Open
fix: stop echoing all request headers in CORS response headers#241Alice39s wants to merge 1 commit intotiagozip:mainfrom
Alice39s wants to merge 1 commit intotiagozip:mainfrom
Conversation
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.
CORS Header Leakage Fix for
@elysiajs/corsSummary
The
@elysiajs/corsplugin ships withallowedHeadersandexposeHeadersdefaulting totrue, which causes it to echo every incoming request header back in theAccess-Control-Allow-HeadersandAccess-Control-Expose-Headersresponse headers – even on non‑preflight responses.This results in internal infrastructure headers (Cloudflare
cf-*,x-forwarded-*,cdn-loop, etc.) appearing in CORS response headers, where they are unnecessary and may leak information about the backend environment.Root Cause
@elysiajs/corsv1.4.1 configuresallowedHeaders: trueandexposeHeaders: trueas defaults.According to the plugin documentation, when either property is set to
truethe plugin callsprocessHeaders(request.headers)– it extracts every header key from the incoming request and joins them into a comma‑separated string for the corresponding CORS response header.cf-connecting-ip,x-forwarded-for,cdn-loop), intoAccess-Control-Allow-HeadersandAccess-Control-Expose-Headers.Fix
Explicitly set
allowedHeadersandexposeHeadersin all three CORS configurations so that only headers required by the client are advertised.allowedHeadersexposeHeaderscap.jsPOST /:siteKey/challenge["content-type"][]siteverify.jsPOST /:siteKey/siteverify["content-type"][]assets.jsGET /assets/*[]Why
["content-type"]?Content-Type: application/jsonis the only non‑CORS‑safelisted request header that the browser sends on thesePOSTendpoints.accept,accept-language, etc.) are CORS‑safelisted request headers and do not require explicit listing inAccess-Control-Allow-Headers– see the CORS protocol specification.Notably, a
Content-Typeheader with a value ofapplication/jsonis not safelisted, therefore it must be explicitly allowed for the preflight to succeed.Why
[]forexposeHeaders?response.headers.get().Access-Control-Expose-Headersheader is only needed when a client must access non‑safelisted response headers.exposeHeaders: []effectively removes theAccess-Control-Expose-Headersheader from the response, preventing unnecessary exposure of internal headers. (A true value would mirror every request header into this header as well.)Before / After
Before – The response reflected a long list of all request headers, including internal infrastructure headers:
After – Only the necessary CORS header is present, and no
Access-Control-Expose-Headersis emitted:access-control-allow-headers: content-type(
Access-Control-Expose-Headersis no longer present unless explicitly required by a future frontend feature.)References