docs: security caveats for cors, proxy, redirect, host and static utils#1470
Conversation
…tatic utils - CORS: warn that regex `origin` entries match unanchored and must be anchored/escaped; fix misleading test examples to safe patterns. - proxy/proxyRequest: document that `Cookie`/`Authorization` are forwarded verbatim and recommend `filterHeaders` for untrusted upstreams. - redirect(): add open-redirect note mirroring `redirectBack`. - getRequestURL/getRequestHost: warn the client-supplied `Host` must not be trusted for security decisions unless pinned/validated upstream. - serveStatic/getMeta/getContents: document that `%2f`/`%5c` stay encoded and safety depends on backends not decoding them; note case-fold and symlink containment responsibilities. 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 (3)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughChangesThe PR adds security guidance to request, proxy, response, static-file, and CORS utility documentation. CORS tests update regex examples and boundary assertions to require anchored, escaped origin patterns. Security documentation and validation
Estimated code review effort: 2 (Simple) | ~10 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: 5
🤖 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 `@docs/2.utils/2.response.md`:
- Around line 67-70: Correct the encoded-backslash security documentation
consistently at docs/2.utils/2.response.md lines 67-70, src/utils/static.ts
lines 20-34, and src/utils/static.ts lines 73-88: explain that single-encoded
%5c is decoded and normalized before getMeta/getContents lookup, while
double-encoded %255c may survive as literal %5c. Retain the warning that
callback backends must not decode the ID, and preserve the case-folding and
symlink-containment guidance where applicable.
In `@src/utils/cors.ts`:
- Around line 26-29: Update the documentation example near the regex-origin
guidance to match its stated behavior: either change “subdomains” to “an
optional subdomain” for the existing single-label pattern, or revise the pattern
to repeat the escaped subdomain label when arbitrary nested subdomains are
intended.
In `@src/utils/proxy.ts`:
- Around line 256-263: Update proxy() in src/utils/proxy.ts#L256-L263 to
implement the documented filterHeaders support, ensuring configured headers such
as Cookie and Authorization are removed before forwarding opts.headers to the
target. Regenerate docs/2.utils/5.proxy.md#L39-L40 from the corrected source
JSDoc so the documentation accurately describes the working credential-filtering
contract.
In `@src/utils/request.ts`:
- Around line 472-478: The JSDoc currently overstates the safety of URL
components. In src/utils/request.ts lines 472-478, revise the wording to state
that pathname and search are not derived from the spoofable host while still
treating them as untrusted input requiring validation or encoding for their
destination sink; update docs/2.utils/1.request.md lines 256-257, or regenerate
it, to match the qualified wording.
In `@test/unit/cors.test.ts`:
- Around line 238-241: Add negative test cases for https://example.com.evil.test
and https://notexample.com in both isCorsOriginAllowed and createOriginHeaders
coverage, asserting each origin is rejected and does not produce allowed CORS
headers. Keep the existing anchored regex configuration and positive cases
unchanged.
🪄 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: cc058801-561a-4b51-9497-c8157b4d1963
📒 Files selected for processing (9)
docs/2.utils/1.request.mddocs/2.utils/2.response.mddocs/2.utils/5.proxy.mdsrc/utils/cors.tssrc/utils/proxy.tssrc/utils/request.tssrc/utils/response.tssrc/utils/static.tstest/unit/cors.test.ts
pi0x
left a comment
There was a problem hiding this comment.
REQUEST CHANGES — one technical inaccuracy in the proxy() credential note; everything else is accurate and well done.
Independent review (I did not author this). Verified against the source on the branch:
Accurate claims (verified in code):
- CORS unanchored:
isCorsOriginAlloweduses_origin.test(origin)(unanchored) — note is correct. New anchored test regexes (/^https:\/\/([a-z0-9-]+\.)?example\.com$/,/^https?:\/\/example\.com$/) are valid inputs and the suite passes. - static
%2f/%5c:serveStaticrunsresolveDotSegmentsthendecodeURI, which preserves reserved%2f; traversal safety does depend ongetMeta/getContentsnot decoding — accurate. redirect/redirectBack:redirectBackenforcesrefererURL.origin === event.url.origin— the "same-origin referers" wording is correct.- Host-header trust and
getRequestURL/getRequestHostnotes are accurate. fetchWithEvent"never forwards the event headers to an external URL": correct — the external branch callsfetch(url, init)with no event headers.
No behavioral code changes anywhere in the diff. pnpm vitest run test/unit/cors.test.ts test/proxy.test.ts test/static.test.ts and pnpm lint pass. (The npx automd drift in docs/2.utils/{4.security,5.proxy,9.more}.md is pre-existing on main — emphasis-style/code-wrap only — not introduced here.)
Requested change — proxy() credential note is inaccurate:
The proxyRequest note is correct: it calls getProxyRequestHeaders(event, { filterHeaders }), so filterHeaders: ["cookie","authorization"] does strip them.
But the note added to the lower-level proxy() (src/utils/proxy.ts ~L257-263, mirrored in docs/2.utils/5.proxy.md) recommends the same filterHeaders: ["cookie","authorization"] — and proxy() never reads opts.filterHeaders (grep confirms it is only consumed in getProxyRequestHeaders, i.e. by proxyRequest/fetchWithEvent). proxy() forwards only headers the caller explicitly passes via opts.headers/opts.fetchOptions.headers; it does not auto-forward the incoming request's Cookie/Authorization at all. So on proxy() the recommended mitigation is a silent no-op — worse than no advice in a security note.
Suggested fix: on the proxy() docstring, either point readers to proxyRequest for filterHeaders-based stripping, or state that proxy() forwards only caller-supplied opts.headers verbatim and credentials are controlled by not passing them (filterHeaders has no effect here). Then regenerate docs/2.utils/5.proxy.md.
🤖 Generated with Claude Code
`proxy()` never reads `opts.filterHeaders` (only `proxyRequest` and `getProxyRequestHeaders` do) and does not auto-forward the incoming request's headers — it only sends what the caller passes via `opts.headers`/`fetchOptions.headers`. Rewrite the note accordingly and point to `proxyRequest` for the `filterHeaders` mitigation. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Addressed the review feedback in 142ea20: the credential-forwarding note on the low-level |
Address CodeRabbit review on #1470: - static: correct the encoded-separator note — `%2f` always survives, but a single-encoded `%5c` is decoded to `\` and normalized away; only a double-encoded `%255c` reaches getMeta/getContents as literal `%5c`. - cors: fix regex example wording — `([a-z0-9-]+\.)?` permits one optional subdomain label, not arbitrary depth. - request: qualify `.pathname`/`.search` as not host-derived but still untrusted input requiring validation/encoding at their sink. - cors test: add negative regex-boundary assertions (`example.com.evil.test`, `notexample.com`) for isCorsOriginAllowed and createOriginHeaders. Regenerated affected automd pages. Co-Authored-By: Claude Opus 4.8 <[email protected]>
# Conflicts: # src/utils/cors.ts
Documentation/JSDoc-only changes (no behavioral code changes) covering five security caveats:
src/utils/cors.ts,test/unit/cors.test.ts): document that regexoriginentries match unanchored and must be anchored + escaped; replace misleading insecure test/doc examples ([/example/],[/example.com/]) with anchored patterns.src/utils/proxy.ts):proxy/proxyRequestforwardCookie/Authorizationverbatim to the target — correct for a same-trust reverse proxy, a leak to untrusted upstreams. RecommendfilterHeaders: ["cookie", "authorization"], noting the contrast withfetchWithEvent.redirect()open-redirect (src/utils/response.ts): security note (mirroringredirectBack) to validate user-derivedlocationagainst an allow-list.src/utils/request.ts):getRequestURL().origin/.hostandgetRequestHost()reflect the client-suppliedHostheader and must not be trusted for security decisions unless pinned/validated upstream.src/utils/static.ts):serveStatickeeps%2f/%5cencoded and safety depends ongetContents/getMetanot decoding them; also document case-insensitive filesystem case-folding and symlink containment (realpath) responsibilities.Regenerated the affected automd docs pages (
docs/2.utils/{1.request,2.response,5.proxy}.md).pnpm vitest run test/unit/cors.test.tsandpnpm lintpass.🤖 Generated with Claude Code
Summary by CodeRabbit