Skip to content

fix(sandbox): cap the Go daemon's fs route request bodies - #6176

Merged
pedrofrxncx merged 1 commit into
mainfrom
fix/daemon-cap-fs-request-body-w3
Aug 18, 2026
Merged

fix(sandbox): cap the Go daemon's fs route request bodies#6176
pedrofrxncx merged 1 commit into
mainfrom
fix/daemon-cap-fs-request-body-w3

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Source: a real resource-bound gap, in the same lane as #6162 (which capped the daemon's outbound MCP JSON-RPC response body) — this caps the daemon's inbound fs request body, which was still unbounded.

Why a maintainer wants this: decodeBody in packages/sandbox/daemon-go/internal/routes/fs.go backs every /fs/* route (read, write, edit, mkdir, unlink, mv, list, write_from_url, upload_to_url) and read the request body with a plain io.ReadAll(r.Body) — no size cap. A caller sending an oversized body could buffer it entirely into the daemon's memory and crash it. Per this repo's own docs, the daemon's health probe is unforgiving: Studio marks the sandbox dead on a single missed probe and tears the pod down mid-session, so an OOM here is a real availability hit, not just a slow request.

Fix: cap the body at maxTransferBytes (500MB) — the bound the daemon already uses for its other file-transfer path (write_from_url/upload_to_url) — via the same io.LimitReader + explicit length check pattern #6162 used for the JSON-RPC response cap.

Regression test: TestDecodeBodyRejectsOversizedRequest in fs_test.go drives decodeBody with an infiniteReader (never hits EOF, no upfront allocation) and asserts it returns a size-limit error instead of buffering forever.

To verify: cd packages/sandbox/daemon-go && go test ./internal/routes/... -run TestDecodeBodyRejectsOversizedRequest -v

Checks run locally: go build ./..., go vet ./internal/routes/..., gofmt -l (clean), and the targeted test above (passes, ~0.5s). Full CI covers the rest.


Summary by cubic

Caps the Go daemon’s /fs/* request bodies at 500MB to prevent OOM and sandbox teardown. Previously decodeBody read an unbounded body with io.ReadAll; now it wraps the body with io.LimitReader(maxTransferBytes+1) and rejects payloads over maxTransferBytes.

  • Applies to all /fs/* routes (read, write, edit, mkdir, unlink, mv, list, write_from_url, upload_to_url); returns a size-limit error. Valid payloads are unaffected.
  • Matches the existing 500MB transfer bound and mirrors the limit + explicit length check pattern from fix(sandbox): cap the Go daemon's MCP JSON-RPC response body #6162.
  • Adds TestDecodeBodyRejectsOversizedRequest using an infinite reader to verify rejection without buffering.

Written for commit 11683c7. Summary will update on new commits.

Review in cubic

@pedrofrxncx
pedrofrxncx enabled auto-merge (squash) August 18, 2026 14:40
decodeBody (used by every /fs/* route: read, write, edit, mkdir, unlink, mv,
list, write_from_url, upload_to_url) read the request body with an unbounded
io.ReadAll. A caller sending an oversized body could buffer it entirely into
the daemon's memory and crash it, tearing down the sandbox pod on the next
missed health probe.

Cap it at maxTransferBytes (500MB), the same bound the daemon already uses
for its other file-transfer path, following the same LimitReader pattern
used to cap the JSON-RPC response body in #6162.

Test: TestDecodeBodyRejectsOversizedRequest drives decodeBody with an
infinite reader and asserts it rejects instead of buffering forever.
@pedrofrxncx
pedrofrxncx force-pushed the fix/daemon-cap-fs-request-body-w3 branch from 28964b0 to 11683c7 Compare August 18, 2026 14:48
@pedrofrxncx
pedrofrxncx merged commit f46db2e into main Aug 18, 2026
26 checks passed
@pedrofrxncx
pedrofrxncx deleted the fix/daemon-cap-fs-request-body-w3 branch August 18, 2026 14:59
decocms Bot pushed a commit that referenced this pull request Aug 18, 2026
PR: #6176 fix(sandbox): cap the Go daemon's fs route request bodies
Bump type: patch

- @decocms/sandbox (packages/sandbox/package.json): 1.55.2 -> 1.55.3
- deploy/helm/sandbox-env (chart 0.16.4) (deploy/helm/sandbox-env/values.yaml deploy/helm/sandbox-env/Chart.yaml): image.tag/appVersion -> 1.55.3

Deploy-Scope: both
pedrofrxncx added a commit that referenced this pull request Aug 18, 2026
A caller-supplied `limit` on /grep had no upper bound, unlike /glob's
matching globMaxResultLimit cap. A large limit lets rg's match lines
accumulate in memory unbounded, the same crash-the-daemon DoS class
#6176 closed for request bodies.
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