Repository navigation
fix(ingest): allow user-agent in the CORS preflight - #1337
JeremyFunk wants to merge 1 commit into
Conversation
Some browsers send a user-agent header that a page set on fetch and list it in Access-Control-Request-Headers. The ingest allow-list did not include it, so the preflight was refused and the request never left the browser. Add it to the gateway allow-list, to the local-mode listener that mirrors it, and to the ingest reference page.
Maple review🟢 Confidence 9/10 · safe to merge Adds
What was checked
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (4)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review. 📝 WalkthroughWalkthroughThe CLI server and ingest service now allow the ChangesCORS request headers
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~8 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to The change adds User-Agent to the CORS preflight allow-lists while retaining the CLI’s existing origin check. No actionable merge-blocking risk is evident, so it appears ready for normal checks. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
What
Adds
user-agentto the request headers the ingest gateway allows in a CORS preflight.apps/ingest/src/main.rs:USER_AGENTin theCorsLayerallow_headerslist, plus a wording fix in theSDK_HINT_HEADERdoc comment, which said no browser lets a page setuser-agent.apps/cli/src/server/serve.ts: the same header in the local-mode listener's allow-list, which mirrors the gateway's for the same SDKs.apps/landing/src/content/docs/reference/ingest.md: the Browsers section lists the allowed headers, so it gainsUser-Agent.Origins, methods, exposed headers, max-age and layer ordering are unchanged.
Why
@maple-dev/effect-sdk/clientsets auser-agentrequest header on every OTLP request. Whether that reaches the network depends on the browser:User-Agentis not a forbidden request-header in the Fetch standard, and it is not CORS-safelisted, so a browser that honours a script-set value lists it inAccess-Control-Request-Headers. The preflight fails with a network error when a listed name is missing fromAccess-Control-Allow-Headers(CORS-preflight fetch, section 4.8, step 7).tower-http0.6.8 answers everyOPTIONSwith the configured list verbatim (cors/allow_headers.rs,AllowHeadersInner::Const); it does not mirror the request, and enforcement is the browser's.Measured on 2026-10-08 in real browsers against a mock ingest whose CORS answers mirror this
CorsLayer:user-agentAccess-Control-Request-Headers/v1/traces,/v1/logs,/v1/metricsPOSTs arriving cross-originauthorization,content-type,user-agent,x-maple-sdk(keyless:content-type,user-agent,x-maple-sdk)user-agentalloweduser-agentSession posts and
@maple-dev/browsernever set the header and are unaffected.Other browsers
User-Agentfrom fetch requests (MDN, forbidden request header note, Chromium issue 571722). Matches the measurement.isForbiddenHeaderNameinHTTPParsers.cppdoes not listUser-Agent,isCrossOriginSafeRequestHeaderin the same file does not safelist it, and r224684 (2017) made the loader keep aUser-Agentthe request already carries. Treat this as a source reading until someone confirms it in Safari.Coverage
CorsLayeris built inline inmainnext to the full application state, and the crate has no preflight or router-level test; tests call the handlers'_innerfunctions directly. Covering it would mean extracting the layer and adding a served-router harness, which is more than this change. It is covered by the browser measurement above and byingest-rust-testscompiling it.apps/cli/test/server-network.test.tshas the exact-header assertion updated and one new case next to the existingauthorizationandx-maple-sdkones.Deploy
fix/sdk-browser-drop-user-agent) stops the browser client from setting the header; the two are independent and can merge in either order.Review bots
CodeRabbit and the Maple review reported no findings on
187f3b3, so nothing was declined.