Skip to content

fix(sandbox-proxy): cap body size on git diff/publish/discard/rebase routes - #5319

Merged
pedrofrxncx merged 1 commit into
mainfrom
fix/sandbox-proxy-git-body-limit-w4
Jul 28, 2026
Merged

fix(sandbox-proxy): cap body size on git diff/publish/discard/rebase routes#5319
pedrofrxncx merged 1 commit into
mainfrom
fix/sandbox-proxy-git-body-limit-w4

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Source: a hardening follow-up to #5316, found while auditing the same file (apps/api/src/api/routes/sandbox-proxy.ts) it touched.

Why: #5316 added a 10MB bodyLimit to the file-op (write/unlink/mkdir/rename/read/glob/grep) and config PUT routes because proxyDaemon reads any forwardJsonBody: true request's body fully into memory via c.req.text() before forwarding it to the daemon. Four sibling routes on the exact same router pass forwardJsonBody: true through that identical code path but were left uncapped: git/diff, git/publish, git/discard, git/rebase. Any authenticated org member (or a buggy client) can still POST an arbitrarily large body to these and have it buffered entirely into the Studio API process's memory — the same gap #5316 just closed elsewhere in this file.

Fix: apply the same bodyLimit middleware (renamed from fileOpBodyLimit to forwardedBodyLimit since it now covers every forwardJsonBody: true route, not just file ops) to the four previously-uncapped routes, rejecting oversized requests with 413 before they're read into memory.

How to verify: grep -n 'forwardJsonBody: true' apps/api/src/api/routes/sandbox-proxy.ts — every one of the 12 matches now sits behind a route registered with forwardedBodyLimit.

Checks run locally: bun run fmt and cd apps/api && bunx tsc --noEmit (both clean). No existing test exercises the full Hono route table for this file (per #5316's own note, and this repo's unit-vs-e2e split) — wiring an already-tested middleware into more routes isn't a new logic path, so no new test was added. Full CI validates the rest.


Summary by cubic

Cap JSON body size to 10MB on git/diff, git/publish, git/discard, and git/rebase sandbox-proxy routes to prevent unbounded memory buffering; oversized requests now return 413. The same limit is applied across all forwardJsonBody: true routes via a shared middleware.

  • Bug Fixes

    • Added 10MB bodyLimit to git/diff, git/publish, git/discard, git/rebase.
    • Stops full-body buffering in proxyDaemon and protects API memory.
  • Refactors

    • Renamed fileOpBodyLimit to forwardedBodyLimit and reused it for all forwardJsonBody: true routes.

Written for commit ab3590e. Summary will update on new commits.

Review in cubic

…routes

#5316 added a 10MB body-size cap to the file-op and config routes on this
router, since proxyDaemon reads forwarded bodies fully into memory via
c.req.text() before forwarding to the daemon. Four sibling routes on the
same router pass forwardJsonBody: true through the identical code path
but were left uncapped: git/diff, git/publish, git/discard, git/rebase.
Any authenticated org member could POST an arbitrarily large body to these
and have it buffered entirely into the Studio API process's memory.

Reused the same bodyLimit middleware (renamed from fileOpBodyLimit to
forwardedBodyLimit since it now covers all forwardJsonBody: true routes)
on the four previously-uncapped routes.
@pedrofrxncx
pedrofrxncx merged commit 7a8fa1d into main Jul 28, 2026
21 of 22 checks passed
@pedrofrxncx
pedrofrxncx deleted the fix/sandbox-proxy-git-body-limit-w4 branch July 28, 2026 12:53
decocms Bot pushed a commit that referenced this pull request Jul 28, 2026
PR: #5319 fix(sandbox-proxy): cap body size on git diff/publish/discard/rebase routes
Bump type: patch

- decocms (apps/api/package.json): 4.139.5 -> 4.139.6

Deploy-Scope: server
pedrofrxncx added a commit that referenced this pull request Jul 28, 2026
…utes (#5330)

#5316/#5319 capped request bodies clients send into this router
(forwardedBodyLimit) because proxyDaemon buffers them fully into memory
via c.req.text() before forwarding. The response side had the same gap:
every route reads the daemon's (or, for preview-fetch/preview-invoke, the
customer's own preview server's) response fully via upstream.text() with
no ceiling. A runaway git diff, a chatty exec script, or a huge preview
page gets buffered entirely into the Studio API process's memory.

Added readBoundedText(), which reads a Response body in chunks and throws
UpstreamPayloadTooLargeError once it exceeds the same 10MB cap already
used for request bodies, instead of buffering an unbounded amount. Wired
it into proxyDaemon, fetchDaemonJson (used by suggest-commit/judge-review),
and the preview-fetch/preview-invoke routes — replacing every remaining
upstream.text() call in this file.
pedrofrxncx added a commit that referenced this pull request Jul 28, 2026
apps/api/src/tools/sandbox/{patch-sandbox-operator,resolve-env,sync-git-credentials}.ts
each PUT to the daemon's /_sandbox/config and, on a non-ok response, read the
error body with a plain res.text() with no size cap. sandbox-proxy.ts already
bounds every proxied response to the same endpoint via readBoundedText()
(#5316/#5319/#5330) — these three call sites hit /_sandbox/config directly
(during publish, rebase, and sandbox start) and were missed, so a
compromised or misbehaving daemon can still make the API process buffer an
unbounded error body into memory on that path.

Extracted readBoundedText()/UpstreamPayloadTooLargeError out of
sandbox-proxy.ts into apps/api/src/lib/bounded-text.ts (no behavior change)
so the tools/sandbox call sites can reuse it without an api-routes ->
tools-layer dependency, and switched all three sites to it with the same
10MB cap sandbox-proxy.ts already applies to this endpoint.
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.

1 participant