Skip to content

fix: add upstream timeout and body size limit to API proxy#150

Open
rohilsurana wants to merge 2 commits into
mainfrom
fix/apis-proxy-timeout-and-body-limit
Open

fix: add upstream timeout and body size limit to API proxy#150
rohilsurana wants to merge 2 commits into
mainfrom
fix/apis-proxy-timeout-and-body-limit

Conversation

@rohilsurana
Copy link
Copy Markdown
Member

@rohilsurana rohilsurana commented Jun 5, 2026

Summary

  • Decode path with decodeURIComponent before traversal check to catch encoded variants like %2e%2e
  • Add 2-minute AbortSignal.timeout to upstream fetch() to prevent indefinitely hanging requests from tying up server workers
  • Add 50MB Content-Length check before parsing the request body to prevent OOM from oversized payloads

Closes #118

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
chronicle Ready Ready Preview, Comment Jun 5, 2026 3:01pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

The 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.

Changes

API Proxy Security Hardening

Layer / File(s) Summary
Request body size validation
packages/chronicle/src/server/api/apis-proxy.ts
Constants define a 50 MB body size limit and 120-second fetch timeout. A content-length header check rejects oversized requests with HTTP 413 Payload Too Large.
Upstream fetch timeout
packages/chronicle/src/server/api/apis-proxy.ts
The upstream fetch call includes an AbortSignal.timeout() to prevent indefinite hangs on external API calls.

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR partially addresses issue #118 requirements: implements fetch timeout and body size limit but does not fix the encoded path traversal vulnerability. Implement path traversal protection using path.resolve() with prefix whitelist to address the encoded path variant check requirement in issue #118.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: adding upstream timeout and body size limit to the API proxy.
Out of Scope Changes check ✅ Passed Changes are limited to adding timeout and body size limit as described in the PR objectives; no unrelated modifications detected in the API proxy file.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description directly addresses the changeset by documenting the two main changes: upstream timeout and body size limit, matching the implementation details in the code changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/apis-proxy-timeout-and-body-limit

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Encoded traversal is still not blocked in proxy path validation.

Line 44 only checks literal '..', so encoded variants like %2e%2e can pass validation and still alter upstream path resolution when Line 48 concatenates URL + path. This leaves the issue #118 traversal 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5bb911c and 5922c22.

📒 Files selected for processing (1)
  • packages/chronicle/src/server/api/apis-proxy.ts

Comment thread packages/chronicle/src/server/api/apis-proxy.ts
Comment thread packages/chronicle/src/server/api/apis-proxy.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: CORS proxy missing timeout, size limits, and encoded path traversal check

1 participant