Skip to content

Security: stop the API mux honouring X-HTTP-Method-Override (CVE-2026-37236) - #3960

Open
rossnelson wants to merge 1 commit into
mainfrom
rossnelson/fe-880-fix-grpc-gateway-sev-issue
Open

rossnelson wants to merge 1 commit into
mainfrom
rossnelson/fe-880-fix-grpc-gateway-sev-issue

Conversation

@rossnelson

Copy link
Copy Markdown
Collaborator

Closes #3955.

Description & motivation 💭

CVE-2026-37236 (9.8). grpc-gateway's runtime.ServeMux honours the X-HTTP-Method-Override header on a POST sent as application/x-www-form-urlencoded, rewriting the method before it routes.

Anything in front of this that allows or denies by method — a proxy, a WAF — is then deciding on a method the mux goes on to discard. A POST that layer permits can arrive here as a DELETE.

Bumping the dependency does not fix it

This is the part worth pausing on. The upstream fix landed in v2.29.0, but it is opt-in — the default behaviour is unchanged even on the newest release. Bumping alone clears the scanner and changes nothing.

So this is both halves:

  1. grpc-ecosystem/grpc-gateway/v2 → v2.30.0
  2. runtime.WithDisableHTTPMethodOverride() on the API mux in server/server/api/handler.go

Design Considerations 🎨

  • Only one mux exists. runtime.NewServeMux has a single call site, so there is no second surface to protect.
  • The dependency change is contained. Only grpc-gateway and two genproto indirects move; nothing else is pulled in.
  • The other advisory is already clear. google.golang.org/grpc is at v1.83.2, past the v1.82.2 fix for CVE-2026-84445, which was reported alongside this one.
  • Not fixed by the option: the path-length fallback (a POST with a form content type falling through to a matching GET handler) is upstream behaviour this option deliberately leaves alone. It does not let a request reach a different RPC than its method allows, so it is not part of this CVE — but it did shape the test, see below.

Testing 🧪

How was this tested 👻

  • Test added that fails without the fix
  • Full server/ suite passes

TestMuxIgnoresHTTPMethodOverride asserts the behaviour, not the version — the version is precisely the part that does not fix it.

It records which gRPC method a request actually reaches, because status codes cannot show this: every unimplemented method answers alike, so a request routed to the wrong RPC is indistinguishable from one routed to the right one. My first two attempts at a status-code assertion both passed against the vulnerable build.

The schedules path routes three methods to three different RPCs, which makes the routing decision unambiguous:

Request Reaches
plain POST CreateSchedule
real DELETE DeleteSchedule
POST + X-HTTP-Method-Override: DELETE must still be CreateSchedule

Confirmed it catches the vulnerability — with the option removed:

--- FAIL: TestMuxIgnoresHTTPMethodOverride
    expected: ".../WorkflowService/CreateSchedule"
    actual  : ".../WorkflowService/DeleteSchedule"
    Messages: X-HTTP-Method-Override must not turn a POST into a DELETE

That is the vulnerability in one assertion: a create becomes a delete.

Full suite passes (the only failure, server/ui/embed.go, is the pre-existing "needs a built UI" setup error that CI resolves by building the UI first).

Checklists

Merge Checklist

  • Both halves included — the bump alone would not have fixed this
  • Test verified to fail against the vulnerable build
  • No dependency cascade beyond grpc-gateway and its genproto indirects

CVE-2026-37236 (9.8). grpc-gateway's ServeMux honours the
X-HTTP-Method-Override header on a POST sent as
application/x-www-form-urlencoded, rewriting the method before it routes.
Anything in front of this that allows or denies by method — a proxy, a WAF
— is then deciding on a method the mux discards, so a POST that layer
permits can arrive here as a DELETE.

The upstream fix is opt-in. It landed in v2.29.0 and the default is
unchanged even on the newest release, so bumping the dependency satisfies
a scanner and changes nothing on its own. Both halves are here: the bump
to v2.30.0, and the option that actually removes the behaviour.

The test asserts the behaviour rather than the version, because the
version is the part that does not fix it. It records which gRPC method a
request reaches, since status codes cannot show that — every unimplemented
method answers alike, so a request routed to the wrong RPC is
indistinguishable from one routed to the right one. Against the schedules
path, a POST carrying `X-HTTP-Method-Override: DELETE` must still reach
CreateSchedule; without the option it reaches DeleteSchedule, which is the
whole of the vulnerability in one assertion.

Only grpc-gateway and two genproto indirects move; nothing else is pulled
in. google.golang.org/grpc is already past CVE-2026-84445, which was the
other advisory reported alongside this one.
@rossnelson
rossnelson requested a review from a team as a code owner September 29, 2026 18:25
@vercel

vercel Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
holocene Ready Ready Preview Sep 29, 2026 6:26pm UTC

Request Review

@andrewzamojc andrewzamojc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

This branch was successfully deployed

1 active deployment
Preview — 8b230c10 Deployed Sep 29, 2026 by vercel[bot]
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.

Security: grpc-gateway v2.22.0 affected by CVE-2026-37236

2 participants