Skip to content

fix(sandbox): cap the Go daemon's config-update body size - #6252

Open
pedrofrxncx wants to merge 1 commit into
mainfrom
fix/daemon-cap-config-body-size-w3
Open

fix(sandbox): cap the Go daemon's config-update body size#6252
pedrofrxncx wants to merge 1 commit into
mainfrom
fix/daemon-cap-config-body-size-w3

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Source: bug found while auditing the Go sandbox daemon (packages/sandbox/daemon-go/internal/routes) for reliability gaps — the same class already fixed for the file-transfer routes (fs.go's decodeBody, see #6215/#6039).

Payoff: ConfigUpdate (PUT /_sandbox/config) and OrgFsConfig both read the request body with a raw, unbounded io.ReadAll(r.Body). A misbehaving or malicious caller can stream an unbounded body into memory and crash the daemon — this is a single static binary per sandbox pod, and Studio tears the pod down on the next missed health probe, so an OOM here kills the whole session.

Failure scenario: POST a multi-GB body to /_sandbox/config or the org-fs config route → io.ReadAll buffers it all into memory with no limit → daemon OOMs/crashes → pod dies. fs.go already guards its routes against exactly this with a capped decodeBody; these two routes were missed.

Fix: added a shared readLimitedBody(r, maxBytes) helper in util.go (same pattern as fs.go's decodeBody, just returning raw bytes since these two callers each unmarshal differently) and wired both routes through it, capped at 1MB — config/org-fs payloads are always small hand-written JSON, never file transfers, so 1MB is generous headroom not a real ceiling.

Regression test: TestReadLimitedBodyRejectsOversizedRequest in util_test.go, mirroring the existing TestDecodeBodyRejectsOversizedRequest in fs_test.go — drives an infinite reader through the helper and asserts it's rejected instead of buffered.

To confirm: cd packages/sandbox/daemon-go && go build ./... && go vet ./... && go test ./internal/routes/...

Locally verified: go build, go vet, gofmt -l (clean), and the full internal/routes test package (including the existing config-redaction tests) — all green. CI validates the rest.


Summary by cubic

Caps the request body for config endpoints at 1 MB to prevent daemon OOMs. Previously, ConfigUpdate and OrgFsConfig read unbounded bodies into memory; now oversized bodies are rejected with 400.

  • Adds readLimitedBody in internal/routes/util.go and applies it to ConfigUpdate and OrgFsConfig.
  • Sets maxConfigBytes to 1 MB; normal small JSON payloads are unaffected.
  • Aligns config routes with the existing fs.go protection pattern.
  • Adds TestReadLimitedBodyRejectsOversizedRequest to prevent regressions.

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

Review in cubic

ConfigUpdate (/_sandbox/config PUT) and OrgFsConfig both read the request
body with an unbounded io.ReadAll(r.Body). A misbehaving or malicious
caller could stream an unbounded body into memory and crash the daemon,
tearing down the sandbox pod on the next missed health probe — the same
failure mode fs.go's decodeBody already guards against for file-transfer
routes.

Adds a shared readLimitedBody helper capped at 1MB (config payloads are
always small hand-written JSON objects, never file transfers) and wires
both routes through it.
@pedrofrxncx
pedrofrxncx enabled auto-merge (squash) August 19, 2026 18:06
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