Skip to content

auth: support model alias claims with body rewrite#42

Open
JannikSt wants to merge 3 commits into
mainfrom
improvement/jwt-model-aliases
Open

auth: support model alias claims with body rewrite#42
JannikSt wants to merge 3 commits into
mainfrom
improvement/jwt-model-aliases

Conversation

@JannikSt
Copy link
Copy Markdown
Member

@JannikSt JannikSt commented Jun 3, 2026

Summary

  • RftClaims gains an optional model_aliases: Vec<String>. allows_model accepts alias hits, and all pin-and-check sites + the transparent-proxy fallback rewrite the request body's model field to the canonical self.model after an alias-only match.
  • Fixes the curriculum-oversight 403 flood: envs that hard-code the platform's user-facing name (e.g. sprints/Llama-3.2-1B-Instruct) are now authorized, and vLLM still only sees the canonical HF path.
  • LoRA matches stay untouched — only alias-only matches get rewritten.

Needs a matching platform change to populate model_aliases in the JWT (incoming PR).


Note

High Risk
Changes JWT model authorization and request-body rewriting on security-sensitive inference paths; incorrect alias/LoRA precedence could mis-route or broaden access.

Overview
JWT run-scoped auth now accepts optional model_aliases on RftClaims, so clients can send a platform-facing model id (e.g. sprints/...) while the token’s canonical model stays the HF path vLLM expects.

After authorization, alias-only requests have their model rewritten to the JWT base in the transparent proxy and in all pin_and_check_model* paths; base model and LoRA names are not rewritten, including when an alias collides with LoRA (LoRA wins). Aliases require a non-empty base model; empty alias entries and alias-without-base fail closed.

Depends on the platform populating model_aliases in issued JWTs.

Reviewed by Cursor Bugbot for commit 11e5481. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Support model alias claims with body rewrite in JWT auth and proxy handlers

  • Adds a model_aliases field to RftClaims in auth.rs; JWTs can now carry a list of alternate model names that are authorized alongside the base model.
  • Adds canonical_for_alias to resolve an alias back to the canonical base model, skipping rewrite for LoRA dispatches.
  • Updates request handlers in server.rs to rewrite the model field in the JSON body to the canonical base model when an alias is matched, before forwarding the request.
  • Behavioral Change: requests using an alias model name now succeed where they previously would have been rejected, and the forwarded body will contain the canonical model name rather than the alias.

Macroscope summarized 11e5481.

The platform's MODEL_HF_PATH_OVERRIDES alias was previously one-way: the
JWT model claim and the orchestrator's TOML model.name both held the
canonical HF path, but envs that hard-code the user-facing name (e.g.
emilschmitz/curriculum-oversight's LLM judge sending
sprints/Llama-3.2-1B-Instruct) hit 403 because the canonical-only claim
required exact-string match.

RftClaims gains an optional model_aliases list. allows_model accepts
alias hits, and pin_and_check_model variants (typed, string, JSON) plus
the transparent-proxy fallback rewrite the request body's model field
to self.model after an alias-only match, so vLLM only ever sees the
canonical served name. Base-model and LoRA matches pass through
unchanged.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5f2c4ad. Configure here.

Comment thread src/auth.rs
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f2c4adcd0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/auth.rs
Comment on lines +129 to +137
pub fn canonical_for_alias(&self, requested: &str) -> Option<String> {
if !self.is_model_alias(requested) {
return None;
}
let base = self.model.as_deref()?;
if base.is_empty() || base == requested {
return None;
}
Some(base.to_string())
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve LoRA names before alias rewrites

When a signed JWT contains a model_aliases entry that is also the allowed LoRA name (or a step-versioned LoRA alias), canonical_for_alias() returns the base model before checking whether requested is a LoRA match. The typed handlers then rewrite model to the base, so a request intended to use the run's adapter is forwarded as a base-model request instead, corrupting LoRA-scoped runs under that alias configuration; the helper's contract says LoRA targets must pass through unchanged.

Useful? React with 👍 / 👎.

@macroscopeapp
Copy link
Copy Markdown

macroscopeapp Bot commented Jun 3, 2026

Approvability

Verdict: Needs human review

Changes to auth module (src/auth.rs) require human review per security sensitivity guidelines. Additionally, there is an unresolved high-severity comment identifying a potential bug where LoRA names matching aliases could be incorrectly rewritten, causing wrong model weights dispatch.

You can customize Macroscope's approvability policy. Learn more.

Bugbot/Codex flagged: if a JWT lists the same string in both
model_aliases and lora (or as a <lora>-... step adapter), the prior
canonical_for_alias would rewrite the request to the base model,
silently swapping a LoRA call for a base-model call.

Fix is to consult the LoRA branch before rewriting — LoRA matches now
take precedence, so the original name reaches vLLM and dispatch works.
Adds tests for both the exact-lora and step-versioned-lora collisions.
@JannikSt
Copy link
Copy Markdown
Member Author

JannikSt commented Jun 3, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18a80dfc0a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/auth.rs
Comment on lines +84 to +85
if self.is_model_alias(requested) {
return true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require a base model before authorizing aliases

When a JWT contains model_aliases but omits model (or sets it empty, which this struct permits via #[serde(default)]), this branch authorizes the alias even though canonical_for_alias later returns None because there is no canonical base to rewrite to. In that misconfigured/lora-only token case the server forwards the alias unchanged on chat/completions/embeddings/responses, broadening the JWT scope instead of failing closed; alias authorization should be gated on a non-empty base model or handled as an error.

Useful? React with 👍 / 👎.

Codex P2: a JWT with model_aliases but no model claim (or an empty
model) would authorize the alias via allows_model and then forward it
to vLLM unchanged, because canonical_for_alias has no canonical to
rewrite to. That broadens JWT scope instead of failing closed.

is_model_alias now requires a non-empty base model claim, so aliases
without a canonical fall back to the same scope as the no-aliases
case.
@JannikSt
Copy link
Copy Markdown
Member Author

JannikSt commented Jun 3, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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