Conversation
- Emit `vary: origin` even when the request origin is rejected, so shared caches never serve a response cached for one origin to another - Always emit `vary: access-control-request-headers` when reflecting request headers with wildcard `allowHeaders` - Reflect the requested method (with `vary: access-control-request-method`) when `methods: "*"` is combined with `credentials: true`, since browsers treat a literal `*` as a method name on credentialed requests - Omit `access-control-expose-headers: *` and warn when combined with `credentials: true` (browsers treat it literally) - Handle `origin: "null"` consistently with `isCorsOriginAllowed` (only reflect `null` when the request origin is actually `null`) Co-Authored-By: Claude Fable 5 <[email protected]>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughChangesCORS behavior updates
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/unit/cors.test.ts (1)
667-670: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAssert the complete merged
Varyvalue.Default wildcard
allowHeadersalso contributesaccess-control-request-headers. The current partial checks would pass if that group were dropped, weakening coverage of the PR’s generalized merge.Proposed assertion
- const vary = eventMock.res.headers.get("vary") ?? ""; - expect(vary).toContain("origin"); - expect(vary).toContain("access-control-request-method"); + expect(eventMock.res.headers.get("vary")).toEqual( + "origin, access-control-request-method, access-control-request-headers", + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/unit/cors.test.ts` around lines 667 - 670, Update the Vary-header assertions in the CORS test to validate the complete merged value, including access-control-request-headers alongside origin and access-control-request-method. Assert the expected combined header value rather than checking only individual substrings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/utils/cors.ts`:
- Around line 35-37: Update the credentials guidance near the `methods`
documentation in `cors.ts` to clarify that `methods: "*"` is supported by
reflecting the requested method when credentials are enabled, rather than
advising credentialed callers never to use it. Keep the existing wildcard
behavior and surrounding documentation unchanged.
---
Nitpick comments:
In `@test/unit/cors.test.ts`:
- Around line 667-670: Update the Vary-header assertions in the CORS test to
validate the complete merged value, including access-control-request-headers
alongside origin and access-control-request-method. Assert the expected combined
header value rather than checking only individual substrings.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 84fdd227-0bd6-47f8-b0cb-b90968e54a96
📒 Files selected for processing (3)
src/utils/cors.tssrc/utils/internal/cors.tstest/unit/cors.test.ts
| * When `credentials` is enabled, browsers treat `"*"` as a literal method name — in that | ||
| * case the requested method is reflected back instead of sending a literal `*`. | ||
| * |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Reconcile the wildcard-method documentation.
Lines 35-37 say methods: "*" is supported through reflection, while Line 65 says credentialed callers should not set methods to "*". Update the credentials documentation to distinguish this supported behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/utils/cors.ts` around lines 35 - 37, Update the credentials guidance near
the `methods` documentation in `cors.ts` to clarify that `methods: "*"` is
supported by reflecting the requested method when credentials are enabled,
rather than advising credentialed callers never to use it. Keep the existing
wildcard behavior and surrounding documentation unchanged.
resolveCorsOptions runs on every request via handleCors, so the credential warnings previously re-logged per request. Route them through a warn-once helper and check the resolved options so a defaulted wildcard exposeHeaders under credentials is diagnosed consistently with origin. Co-Authored-By: Claude Opus 4.8 <[email protected]>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
Fixes several spec-level correctness issues in the CORS utils found during a review of
src/utils/cors.ts/src/utils/internal/cors.ts.vary: originwas missing when the origin is rejected (cache poisoning)When
originis an allowlist/function, an allowed origin gotaccess-control-allow-origin+vary: origin, but a rejected origin got neither. The response varies by request origin without declaring it, so a shared cache could store the ACAO-less response from a disallowed origin and serve it to an allowed one (or cache the reflected header and serve it to everyone).createOriginHeadersnow always emitsvary: originwhen the origin option is not"*".Wildcards are treated literally on credentialed requests
Per the Fetch spec,
*inaccess-control-allow-methods/access-control-expose-headersis a literal token when credentials are included:methods: "*"+credentials: truenow reflectsaccess-control-request-methodback (withvary: access-control-request-method) instead of sending a literal*that browsers would reject — same technique already used forallowHeaders.exposeHeaders: "*"+credentials: truenow omits the useless header and logs a warning suggesting an explicit list.vary: access-control-request-headerswas missing when the header is absentWith wildcard
allowHeaders, the preflight response reflectsaccess-control-request-headers, but novarywas declared when the request omitted that header — same undeclared-variance class as the origin issue.origin: "null"was inconsistent withisCorsOriginAllowedcreateOriginHeadersunconditionally emittedaccess-control-allow-origin: nullfor any request origin, whileisCorsOriginAllowedonly matches a literal"null"origin. Both now agree:nullis only reflected when the request origin is actuallynull.The
varymerge inappendCorsPreflightHeaderswas generalized since three header groups can now emitvaryindependently.Testing
varybehavior and added regression tests for each fix (test/unit/cors.test.ts, 44 tests)🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
methods: "*"by reflecting the requested method when available.access-control-expose-headersforexposeHeaders: "*"when credentials are enabled.Varyheader behavior for allowed and rejected origins, and for preflight responses (including combined variation across relevant dimensions).Tests
Vary/header outputs.