Skip to content

fix(network): refuse protocol upgrades on GraphQL endpoints - #3841

Merged
johntmyers merged 3 commits into
NVIDIA:mainfrom
shiju-nv:fix/graphql-upgrade-inspection
Sep 30, 2026
Merged

johntmyers merged 3 commits into
NVIDIA:mainfrom
shiju-nv:fix/graphql-upgrade-inspection

Conversation

@shiju-nv

@shiju-nv shiju-nv commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

On a protocol: graphql endpoint, an accepted protocol upgrade can switch the connection to a raw relay, where later messages bypass GraphQL operation checks. Refuse requests carrying an Upgrade header with 403 Forbidden after validating the HTTP head and endpoint authority, before reading the body or forwarding the request, in both enforce and audit mode. Ordinary GraphQL HTTP requests continue through body inspection and operation policy.

Related Issue

No issue required: this is a localized correction to protocol-upgrade handling, extending the refusal already merged in #3753 to GraphQL endpoints.

Changes

  • Use one exhaustive protocol mapping for request refusal and defensive handling of unexpected 101 Switching Protocols responses.
  • Cover single-endpoint, route-selected, and forward-proxy requests, including audit mode and queryless subscription handshakes.
  • Reject single-endpoint upgrade requests without waiting for a declared body, including incomplete and oversized bodies. Preserve malformed-framing rejection and the specific denial for an endpoint-authority mismatch.
  • Document GraphQL over WebSocket through protocol: websocket with GraphQL operation rules on a separate server path or port. Both inspected transports cannot share the same host, port, and path.
  • Retain controls for ordinary GraphQL requests and WebSocket subscriptions, and test allowed and denied GraphQL POST bodies.

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)

Local verification passed package formatting, changed-file license checks, git diff --check, cargo check -p openshell-supervisor-network --locked, and seven exact library regressions. The regressions cover withheld bodies, framing and authority validation, ordinary POST inspection, existing upgrade refusals, credential denial, and chunked request sequencing. The retained reproduction failed on the previous head and its base.

Hosted Branch Checks and standard runtime E2E passed on 71346cb1834e3ffe41cf0b02d613a4ca43747a0a. The optional GPU and Kubernetes HA/credential-driver suites were skipped.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

Refuse Upgrade headers before forwarding GraphQL-over-HTTP requests.
Share the protocol refusal table with JSON-RPC and MCP, and close
unexpected protocol switches before relaying frames.

Keep GraphQL-over-WebSocket inspection on separate WebSocket endpoints.
Cover upgrade refusal, audit mode, subscription handshakes, and ordinary
HTTP and WebSocket controls. Update the current policy documentation.

Signed-off-by: Shiju <shiju@nvidia.com>
Preserve upstream architecture documentation removal and retain GraphQL upgrade guidance in the published policy pages.

Signed-off-by: Shiju <shiju@nvidia.com>
@johntmyers johntmyers added the gator:in-review Gator is reviewing or awaiting PR review feedback label Sep 30, 2026

@johntmyers johntmyers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gator-agent

PR Review Status

A sandboxed workload using the supported single-endpoint GraphQL path can send an upgrade request with an oversized or incomplete body; the relay inspects that body before applying this PR's new refusal, so it can return no documented 403 or wait for missing bytes instead of rejecting immediately.

Action required: move the single-endpoint GraphQL upgrade check ahead of body inspection and add the regression test described inline.

Blocking findings:

  • GATOR-e1e76599-01: the single-endpoint GraphQL relay rejects upgrades too late

Carried findings:

  • None

Non-blocking suggestions:

  • None
Gator metadata
  • Validation: Project-valid localized network-policy security correction from a repository maintainer
  • Docs: Fern policy documentation updated for the changed user-visible behavior
  • Checks: Existing current-head required checks are green; E2E has not been dispatched
  • E2E: test:e2e will be required after review feedback is resolved
  • Head SHA: e1e7659978329b83574a80617f610ac0e1aa7234
  • Base SHA: 33a8eac196a21aff3125dea46462a4591bcb5d0b
  • Merge base SHA: 33a8eac196a21aff3125dea46462a4591bcb5d0b
  • Patch ID: 41a19ef33300612608f9343b4d6286b40ddd450d
  • Gator payload: 9
  • Review mode: initial
  • Previous reviewed SHA: none
  • Review budget exhausted: no
  • Maintainer decision required: no
  • Next state: gator:in-review

Comment thread crates/openshell-supervisor-network/src/l7/rest.rs
Validate the HTTP head and endpoint authority before upgrade refusal, then inspect ordinary GraphQL bodies. Preserve missing-authority credential rejection after body inspection.

Signed-off-by: Shiju <shiju@nvidia.com>
@johntmyers johntmyers added the test:e2e Requires end-to-end coverage label Sep 30, 2026
@github-actions

Copy link
Copy Markdown

Label test:e2e applied for 71346cb. Open the existing run and click Re-run all jobs to execute with the label set. The run will execute the standard E2E suite after building the required gateway, sandbox, and supervisor images once. The matching required CI gate status on this PR will flip green automatically once the run finishes.

@johntmyers johntmyers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gator-agent

PR Review Status

Thanks @shiju-nv. I checked the new single-endpoint GraphQL flow and its withheld-body regressions: the relay now validates the request head and endpoint authority, refuses unsupported upgrades before reading the body, and preserves ordinary GraphQL body inspection. The prior finding is resolved, and the follow-up review found no new blockers.

Blocking findings:

  • No blocking findings remain

Carried findings:

  • GATOR-e1e76599-01: resolved by the current head; the Gator-owned thread has been closed
Gator metadata
  • Validation: Project-valid localized network-policy security correction from a repository maintainer
  • Docs: Relevant Fern policy documentation is updated
  • Checks: Existing required checks are green; the required current-head E2E attempt is running
  • E2E: test:e2e applied; Branch E2E Checks run 36686663426, attempt 2, is in progress
  • Head SHA: 71346cb1834e3ffe41cf0b02d613a4ca43747a0a
  • Base SHA: 33a8eac196a21aff3125dea46462a4591bcb5d0b
  • Merge base SHA: 33a8eac196a21aff3125dea46462a4591bcb5d0b
  • Patch ID: bf5e22f167555d7086b52f2389d02f8cf3739512
  • Gator payload: 9
  • Review mode: follow_up
  • Previous reviewed SHA: e1e7659978329b83574a80617f610ac0e1aa7234
  • Review budget exhausted: no
  • Maintainer decision required: no
  • Next state: gator:watch-pipeline

@johntmyers johntmyers added gator:watch-pipeline Gator is monitoring PR CI/CD status gator:approval-needed Gator completed review; maintainer approval needed and removed gator:in-review Gator is reviewing or awaiting PR review feedback gator:watch-pipeline Gator is monitoring PR CI/CD status labels Sep 30, 2026
@johntmyers
johntmyers added this pull request to the merge queue Sep 30, 2026
@johntmyers johntmyers added gator:merge-ready and removed gator:approval-needed Gator completed review; maintainer approval needed labels Sep 30, 2026
Merged via the queue into NVIDIA:main with commit 374c035 Sep 30, 2026
143 of 146 checks passed
@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Monitoring Complete

Monitoring is complete because this PR has merged.

Final status: Gator review found no remaining blockers on the final head, the required core E2E suite passed, and maintainer approval was present before merge.

I removed the active gator:* label because there is nothing left for gator to monitor on this PR.

Gator metadata
  • Head SHA: 71346cb1834e3ffe41cf0b02d613a4ca43747a0a
  • Gator payload: 9
  • Previous state: gator:merge-ready
  • Next state: monitoring complete

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants