Skip to content

fix(proxy): cap request bodies and gate browser origins - #108

Closed
woodsonl wants to merge 1 commit into
NVIDIA:developfrom
woodsonl:fix/proxy-body-limit-and-origin-gate
Closed

woodsonl wants to merge 1 commit into
NVIDIA:developfrom
woodsonl:fix/proxy-body-limit-and-origin-gate

Conversation

@woodsonl

@woodsonl woodsonl commented Sep 22, 2026 •

Copy link
Copy Markdown

Description

Request bodies are bounded. Inbound bodies are buffered once so each
failover attempt can replay them, with no size limit, so any loopback caller
could make the proxy read an unbounded body into memory before routing. The
buffer is now capped at 32 MiB and anything larger is refused with 413 before
a candidate is resolved or scheduler capacity is reserved. Long-context prompts
fit well below the cap.

Browser origins are gated at entry. The loopback listener is reachable from
a browser page on any origin, and a simple cross-origin POST needs no
preflight, so header policy alone cannot stop an unlisted page from driving the
local engines. A deny-by-default allowlist now runs ahead of forwarding. A
request that carries an Origin is admitted only from an exact origin listed
in NVPAIR_PROXY_ALLOWED_ORIGINS; anything else is refused with 403
origin-not-allowed. Callers that send no Origin (the Electron main process,
CLI tools, health probes) are unaffected. This sits above the existing
per-engine intersection policy, which still decides what an admitted origin may
read.

Release intent

Changelog title

Proxy caps request bodies and gates browser origins

Changelog body

The local proxy refuses request bodies larger than 32 MiB instead of buffering
them without limit. Browser callers are admitted only from origins the operator
lists in NVPAIR_PROXY_ALLOWED_ORIGINS; a browser origin that is not listed is
refused before it reaches an engine, while non-browser callers are unaffected.

Bumps

  • services: patch
  • nvpair-cluster-manager: none
  • nvpair-engine-manager: none
  • nvpair-errors: none
  • nvpair-job-scheduler: none
  • nvpair-manual-nodes: none
  • nvpair-node-info: none
  • nvpair-node-scanner: none
  • nvpair-node-settings: none
  • nvpair-proxy: patch
  • nvpair-tui: none
  • nvpair-ui-broker: none
  • nvpair-workload-manager: none

Scope

Included: the body-size cap and 413 path, the allowlist gate and its
NVPAIR_PROXY_ALLOWED_ORIGINS configuration, the shared cors allowlist
helper, and tests for both.

Excluded: the per-engine CORS intersection policy is unchanged; the gate runs
before it and only admits or refuses.

Validation

  • go build ./... and go test ./... in services/shared and
    services/nvpair-proxy
  • services/nvpair-proxy/body_limit_test.go covers the 413 path, and
    ingress_test.go covers the allowlist gate.

Risk

Behavior change for browser clients: with NVPAIR_PROXY_ALLOWED_ORIGINS unset
(the default), a browser Origin is refused. Non-browser callers are
unaffected, and the setting is comma-separated exact origins.

Checklist

  • I have read the Contributing Guidelines.
  • Every commit is signed off (git commit -s), certifying the Developer Certificate of Origin.
  • New or existing tests cover the change.
  • Relevant documentation is updated.
  • I checked the diff, changed filenames, and commit messages for credentials, private data, internal URLs, internal issue identifiers, and generated artifacts.
  • I recorded the validation commands and results above.
  • I declared version bumps in the release-intent block above. services/versions.json is written by automation — do not edit it by hand.

…ntry

Two additions at the proxy's request boundary:

- Inbound bodies are buffered once so each failover attempt can replay
  them, with no size limit — any loopback caller could make the proxy read
  an unbounded body into memory before routing. Cap the buffer at 32 MiB
  and refuse anything larger with 413 before resolving a candidate or
  reserving scheduler capacity. A mid-body read error is refused the same
  way rather than forwarded truncated, and the 413 uses the same JSON error
  shape as every other proxy rejection. Long-context prompts fit well
  below the cap.

- The loopback listener is reachable from a browser page on any origin,
  and a simple cross-origin POST needs no preflight, so header policy
  alone cannot stop an unlisted page from driving the local engines. Add a
  deny-by-default allowlist gate ahead of forwarding: a request carrying an
  Origin is admitted only from an exact origin listed in
  NVPAIR_PROXY_ALLOWED_ORIGINS, otherwise it is refused with 403
  origin-not-allowed. Callers that send no Origin (Electron main, CLI,
  probes) are unaffected. This sits above the existing per-engine
  intersection policy, which still decides what an admitted origin may
  read.

Signed-off-by: woodsonl <65194841+woodsonl@users.noreply.github.com>
@woodsonl woodsonl closed this Sep 24, 2026
@woodsonl
woodsonl deleted the fix/proxy-body-limit-and-origin-gate branch September 24, 2026 05:25
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