fix: add upstream timeout and body size limit to API proxy#150
fix: add upstream timeout and body size limit to API proxy#150rohilsurana wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe proxy API handler is hardened with two security guards: incoming requests exceeding 50 MB are rejected with HTTP 413, and upstream fetch calls are aborted after 120 seconds. Both guards protect the proxy from resource exhaustion and hanging connections. ChangesAPI Proxy Security Hardening
🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/chronicle/src/server/api/apis-proxy.ts (1)
44-46:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEncoded traversal is still not blocked in proxy path validation.
Line 44 only checks literal
'..', so encoded variants like%2e%2ecan pass validation and still alter upstream path resolution when Line 48 concatenates URL + path. This leaves the issue#118traversal gap unresolved.Suggested fix pattern
- if (/^[a-z]+:\/\//i.test(path) || path.includes('..')) { + const decodedPath = decodeURIComponent(path); + if (/^[a-z]+:\/\//i.test(decodedPath) || decodedPath.includes('..')) { throw new HTTPError({ status: 400, message: 'Invalid path' }); }+ // Prefer normalized path resolution against an allowed base prefix. + // Reject when normalized path escapes the allowed API prefix.Also applies to: 48-48
🤖 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 `@packages/chronicle/src/server/api/apis-proxy.ts` around lines 44 - 46, The current validation uses path.includes('..') and a scheme regex which misses percent-encoded traversal; modify the check to first safely decode the incoming path (use a try/catch around decodeURIComponent on the variable path) and then validate the decoded value: reject if /^[a-z]+:\/\//i.test(path) OR decodedPath.includes('..') OR /(^|\/)\.(?:\.|\/)/.test(decodedPath) (or equivalent normalized traversal check), and continue to throw the same HTTPError when any of those conditions match; update the validation around the existing path variable and the throw HTTPError call so encoded variants like %2e%2e are caught.
🤖 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 `@packages/chronicle/src/server/api/apis-proxy.ts`:
- Around line 21-24: Reject requests with missing/invalid Content-Length by
validating contentLength is finite and >= 0 (reject with HTTPError 411/413 or
400 as your policy) instead of trusting Number(...) alone, and when consuming
the body (the code that currently calls JSON.parse / reads full body) stream and
count bytes while reading from event.req (or Request.body) and abort with
HTTPError({status:413,...}) as soon as accumulated bytes exceed MAX_BODY_BYTES;
keep the existing MAX_BODY_BYTES and HTTPError usage and apply these checks
around contentLength, event.req.headers and the body-reading logic so a
deceptive/malformed header cannot bypass the limit.
- Line 54: The request body is being dropped for valid falsy JSON values because
the fetch options use a truthy check; in the code that sets "body: body ?
JSON.stringify(body) : undefined" (in apis-proxy.ts), change the condition to
check for undefined/null (e.g., body !== undefined or body != null per contract)
and JSON.stringify when present so scalar values like 0, false, and "" are
forwarded upstream; update the line that constructs the request options (the
body assignment) accordingly and keep undefined when no body is intended.
---
Outside diff comments:
In `@packages/chronicle/src/server/api/apis-proxy.ts`:
- Around line 44-46: The current validation uses path.includes('..') and a
scheme regex which misses percent-encoded traversal; modify the check to first
safely decode the incoming path (use a try/catch around decodeURIComponent on
the variable path) and then validate the decoded value: reject if
/^[a-z]+:\/\//i.test(path) OR decodedPath.includes('..') OR
/(^|\/)\.(?:\.|\/)/.test(decodedPath) (or equivalent normalized traversal
check), and continue to throw the same HTTPError when any of those conditions
match; update the validation around the existing path variable and the throw
HTTPError call so encoded variants like %2e%2e are caught.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 41843b07-0915-44f0-8c9a-9ca5b0cf66cc
📒 Files selected for processing (1)
packages/chronicle/src/server/api/apis-proxy.ts
Summary
decodeURIComponentbefore traversal check to catch encoded variants like%2e%2eAbortSignal.timeoutto upstreamfetch()to prevent indefinitely hanging requests from tying up server workersContent-Lengthcheck before parsing the request body to prevent OOM from oversized payloadsCloses #118