From 6fd190d8258661a7109cff7d4fd67a9cd6f36950 Mon Sep 17 00:00:00 2001 From: Krishnan Prashanth Date: Wed, 15 Jul 2026 22:34:16 -0700 Subject: [PATCH] fix(frontend): reject nested chat_template in chat_template_args Signed-off-by: Krishnan Prashanth --- .../src/protocols/openai/chat_completions.rs | 1 + lib/llm/src/protocols/openai/validate.rs | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/lib/llm/src/protocols/openai/chat_completions.rs b/lib/llm/src/protocols/openai/chat_completions.rs index 2144f5dbc8cf..4bae17c96997 100644 --- a/lib/llm/src/protocols/openai/chat_completions.rs +++ b/lib/llm/src/protocols/openai/chat_completions.rs @@ -531,6 +531,7 @@ impl OpenAIOutputOptionsProvider for NvCreateChatCompletionRequest { impl ValidateRequest for NvCreateChatCompletionRequest { fn validate(&self) -> Result<(), anyhow::Error> { validate::validate_no_unsupported_fields(&self.unsupported_fields)?; + validate::validate_chat_template_args(self.chat_template_args.as_ref())?; validate::validate_messages(&self.inner.messages)?; validate::validate_model(&self.inner.model)?; // none for store diff --git a/lib/llm/src/protocols/openai/validate.rs b/lib/llm/src/protocols/openai/validate.rs index 0c7f4b0bc2bd..c39712c27d1f 100644 --- a/lib/llm/src/protocols/openai/validate.rs +++ b/lib/llm/src/protocols/openai/validate.rs @@ -804,6 +804,19 @@ where Ok(Some(value)) } +/// A nested `chat_template` bypasses Dynamo's top-level rejection and is +/// promoted into the rendered template, so block it for every chat processor. +pub fn validate_chat_template_args( + chat_template_args: Option<&std::collections::HashMap>, +) -> Result<(), anyhow::Error> { + if let Some(args) = chat_template_args + && args.contains_key("chat_template") + { + anyhow::bail!("`chat_template` is not supported inside `chat_template_args`"); + } + Ok(()) +} + #[cfg(test)] mod tests { use std::collections::HashMap; @@ -816,6 +829,23 @@ mod tests { HashMap::from([("experimental_field".to_string(), json!("value"))]) } + #[test] + fn validate_chat_template_args_rejects_nested_chat_template() { + let args = HashMap::from([( + "chat_template".to_string(), + json!("{% for _ in range(10**9) %}x{% endfor %}"), + )]); + let err = validate_chat_template_args(Some(&args)).unwrap_err(); + assert!(err.to_string().contains("chat_template")); + } + + #[test] + fn validate_chat_template_args_accepts_other_keys() { + let args = HashMap::from([("enable_thinking".to_string(), json!(false))]); + validate_chat_template_args(Some(&args)).unwrap(); + validate_chat_template_args(None).unwrap(); + } + #[test] fn validate_no_unsupported_fields_rejects_unknown_fields_by_default() { let err = validate_no_unsupported_fields_with_ignore(&unknown_fields(), false).unwrap_err();