Skip to content

fix(llm-gateway): reject priority header#341

Merged
along-2017 merged 2 commits into
mainfrom
fix/llm-gateway-reject-priority-header
Jul 22, 2026
Merged

fix(llm-gateway): reject priority header#341
along-2017 merged 2 commits into
mainfrom
fix/llm-gateway-reject-priority-header

Conversation

@along-2017

@along-2017 along-2017 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

TL;DR

X-Priority is a gateway-owned trusted header. A client must not be able to self-assign it. This rejects any LLM API request that arrives with a client-supplied X-Priority with 400 Bad Request.

Additional Details

  • The reject is route middleware on the LLM route group, so it covers exactly the LLM endpoints on that group (/v1/chat/completions, /v1/responses, /v1/embeddings, and any route later added to the group) and leaves routes registered directly on the server, such as the health endpoints, untouched.
  • Group middleware runs after the global middlewares, so authentication still runs first: an unauthenticated request gets 401 before the header check, and the reject happens before any outbound request is built.
  • The check fires on header presence rather than value, so a present-but-empty X-Priority is rejected too.

For the Reviewer

  • api/priority_guard.go is the guard; api/routes.go wires it onto the LLM group via e.Group("", rejectClientSuppliedPriority).
  • api/priority_guard_test.go drives the real RegisterRoutes wiring, so it fails if the guard is ever dropped from the group.

For QA

  • go test ./api/... and bazel test //api:api_test pass. Manual: a request to any of the three LLM endpoints carrying X-Priority (any value, including empty) returns 400; /healthz with X-Priority still returns 200.

Issues

Closes #187.

Checklist

  • I am familiar with the Contributing Guidelines.
  • I have signed off my commits for Developer Certificate of Origin (DCO) compliance.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

Summary by CodeRabbit

  • Bug Fixes
    • LLM API endpoints now reject any client-supplied X-Priority header with an HTTP 400 response indicating the header is reserved.
    • Request priority is handled by the gateway, ensuring consistent behavior across LLM routes.
    • /healthz and /readyz remain unaffected even when X-Priority is present.
  • Documentation
    • Updated routing guidance to state that X-Priority is reserved for gateway use.
  • Tests
    • Added coverage to verify the middleware behavior, scoping, and middleware ordering.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 59e9e768-79d7-4662-983c-84a6f4c00ae7

📥 Commits

Reviewing files that changed from the base of the PR and between 2d0e3e8 and fbedf6e.

📒 Files selected for processing (1)
  • src/invocation-plane-services/llm-api-gateway/api/priority_guard_test.go

📝 Walkthrough

Walkthrough

The LLM API gateway now rejects client-supplied X-Priority headers on grouped LLM routes with HTTP 400, preserves authorization ordering, leaves health endpoints unaffected, and documents the reserved-header behavior.

Changes

LLM priority header rejection

Layer / File(s) Summary
Priority guard and route wiring
src/invocation-plane-services/llm-api-gateway/api/priority_guard.go, src/invocation-plane-services/llm-api-gateway/api/routes.go, src/invocation-plane-services/llm-api-gateway/api/BUILD.bazel, src/invocation-plane-services/llm-api-gateway/README.md
Adds route-scoped middleware that returns HTTP 400 for client-supplied X-Priority, registers the middleware, includes the new sources in Bazel targets, and documents the behavior.
Route behavior validation
src/invocation-plane-services/llm-api-gateway/api/priority_guard_test.go, src/invocation-plane-services/llm-api-gateway/api/BUILD.bazel
Tests rejection across LLM routes and header values, authorization-before-rejection ordering, health endpoint scope, and forwarding when the header is absent.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Echo
  participant NVCFAuth
  participant PriorityGuard
  participant LLMHandler
  Client->>Echo: Send LLM request
  Echo->>NVCFAuth: Authenticate request
  NVCFAuth->>PriorityGuard: Continue authorized request
  PriorityGuard-->>Client: Return 400 for X-Priority
  PriorityGuard->>LLMHandler: Forward request without X-Priority
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: rejecting client-supplied priority headers in llm-gateway.
Linked Issues check ✅ Passed The PR satisfies #187 by returning 400 for X-Priority, allowing requests without it, and adding coverage for both paths.
Out of Scope Changes check ✅ Passed The README, route wiring, guard, and tests all support the linked header-rejection behavior, with no obvious unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/llm-gateway-reject-priority-header

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Comment @coderabbitai help to get the list of available commands.

@along-2017 along-2017 self-assigned this Jul 22, 2026
@along-2017
along-2017 force-pushed the fix/llm-gateway-reject-priority-header branch 2 times, most recently from 223a470 to c860c2b Compare July 22, 2026 05:50
X-Priority is a gateway-owned trusted header: the gateway sets it from the
priority resolved by NVCF API at auth time, so a client must not be able to
self-assign it and influence Stargate routing or queue admission.

Reject any LLM API request that arrives with an X-Priority header, returning
400 Bad Request before any outbound request is built. The check fires on
header presence rather than value, so a present-but-empty X-Priority is
rejected too. The guard is route middleware on the LLM route group, so it
covers exactly the proxied endpoints (/v1/chat/completions, /v1/responses,
/v1/embeddings, and any route later added to the group) and leaves
non-proxied routes such as the health endpoints untouched. Because group
middleware runs after the global middlewares, authentication still runs
first: an unauthenticated request gets 401 before the header check.

Signed-off-by: along <along@nvidia.com>
@along-2017
along-2017 force-pushed the fix/llm-gateway-reject-priority-header branch from c860c2b to 2d0e3e8 Compare July 22, 2026 16:29
@along-2017
along-2017 marked this pull request as ready for review July 22, 2026 17:37
@along-2017
along-2017 requested a review from a team as a code owner July 22, 2026 17:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/invocation-plane-services/llm-api-gateway/api/priority_guard_test.go`:
- Around line 46-53: Extend the priority test matrix around the existing guarded
routes and priority values with a case for an LLM route that omits X-Priority.
Assert that this request is not rejected by the priority guard and proceeds to
authorization, while preserving the existing explicit and empty-header cases and
the /healthz behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 267a28d9-6e0b-40bd-8135-23480fdeb5a8

📥 Commits

Reviewing files that changed from the base of the PR and between 8460ce2 and 2d0e3e8.

📒 Files selected for processing (5)
  • src/invocation-plane-services/llm-api-gateway/README.md
  • src/invocation-plane-services/llm-api-gateway/api/BUILD.bazel
  • src/invocation-plane-services/llm-api-gateway/api/priority_guard.go
  • src/invocation-plane-services/llm-api-gateway/api/priority_guard_test.go
  • src/invocation-plane-services/llm-api-gateway/api/routes.go

…iority

Add a positive control asserting rejectClientSuppliedPriority forwards a
request that carries no X-Priority to the next handler. The existing matrix
only covered rejection, so a guard that rejected unconditionally would have
satisfied every case while breaking all legitimate LLM traffic; this test
fails on exactly that mutation. Exercises the guard branch directly because
a no-header request reaching the real LLM handler needs the full provider
stack, which is out of scope for a guard test.

Signed-off-by: along <along@nvidia.com>
@along-2017
along-2017 added this pull request to the merge queue Jul 22, 2026
Merged via the queue into main with commit 97a4611 Jul 22, 2026
13 checks passed
@along-2017
along-2017 deleted the fix/llm-gateway-reject-priority-header branch July 22, 2026 21:00
@balajinvda

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version nvcf-llm-api-gateway-v0.10.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reject client-supplied request priority headers

3 participants