Skip to content

fix(sandbox): cap the Go daemon's inline dispatch request body size - #6447

Merged
pedrofrxncx merged 1 commit into
mainfrom
fix/dispatch-cap-body-size-w3
Aug 24, 2026
Merged

fix(sandbox): cap the Go daemon's inline dispatch request body size#6447
pedrofrxncx merged 1 commit into
mainfrom
fix/dispatch-cap-body-size-w3

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Source: bounded resource fix (C3), same DoS-bound category as the already-merged #6215/#6039 fs caps and the open #6252 config-body cap — this is the /dispatch entry point, which none of those touch.

The gap: HandleDispatch in packages/sandbox/daemon-go/internal/dispatch/dispatch.go read the request body with a plain io.ReadAll(r.Body) — no size limit. Its sibling path, handleOffloadDispatchFetchOffloadedMessages (offload.go), already caps external message fetches at maxOffloadBytes (32MB) with a Content-Length/read-limit check specifically because a large payload is expected to go through that offload path, not inline. The inline path had no equivalent bound, so one oversized POST to /dispatch could buffer arbitrarily large bytes into the pod's memory before validation even runs.

Fix: wrap the read in http.MaxBytesReader(w, r.Body, maxDispatchBodyBytes) (aliased to the existing maxOffloadBytes constant, so the two caps stay in sync) and answer 413 body_too_large via errors.As on *http.MaxBytesError instead of buffering past the cap.

Verification: TestDispatchRejectsOversizedBody sends a maxDispatchBodyBytes+1-byte body through HandleDispatch and asserts a 413. Ran go build ./..., go vet ./internal/dispatch/..., gofmt -l (clean), and go test ./internal/dispatch/... (full package, all green) locally — CI runs the rest.

A reviewer can confirm with: cd packages/sandbox/daemon-go && go test ./internal/dispatch/... -run TestDispatchRejectsOversizedBody -v.


Summary by cubic

Caps the Go sandbox daemon’s inline /dispatch request body to prevent unbounded memory use. Previously io.ReadAll buffered the full body; now the read is limited to maxOffloadBytes (32MB) and oversized bodies return 413.

  • Uses http.MaxBytesReader in HandleDispatch; on overflow returns 413 body_too_large before buffering. Other read/JSON errors still return 400 bad_json.
  • Aligns the inline path with the offload path by aliasing the cap to maxOffloadBytes.
  • Adds TestDispatchRejectsOversizedBody to assert the 413 response.

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

Review in cubic

The /dispatch route buffered r.Body with an unbounded io.ReadAll while
its sibling offload path (FetchOffloadedMessages) already caps at
maxOffloadBytes (32MB). A large inline dispatch body had no such limit,
letting one request park up to the full body size in memory on the pod.

Wraps the read in http.MaxBytesReader at maxOffloadBytes and answers 413
on overflow instead of buffering past the cap.
@pedrofrxncx
pedrofrxncx enabled auto-merge (squash) August 24, 2026 15:49
@pedrofrxncx
pedrofrxncx merged commit aec1572 into main Aug 24, 2026
33 checks passed
@pedrofrxncx
pedrofrxncx deleted the fix/dispatch-cap-body-size-w3 branch August 24, 2026 15:50
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