High

vLLM Tool Schema Malformed Pattern or Type Field

An attacker sends a normal-looking API request to an LLM server, but hides a broken or resource-exhausting regex pattern inside the tool/function schema. When vLLM tries to compile that pattern into a native regex, the worker process crashes and stays down until someone manually restarts it — a denial-of-service against the model-serving endpoint.

How the attack works

The attacker crafts an OpenAI-style tool/function definition as part of a normal inference request. Inside that definition, the 'pattern' field contains a regex with a fatal flaw: an unclosed character class, a nested quantifier known to cause catastrophic backtracking (ReDoS), or an absurdly large repetition count. Alternatively, the 'type' field — which JSON Schema requires to be a string or array of strings — is set to a non-string value like true, false, null, or a number. The request is sent to the inference endpoint, where vLLM renders the schema through Jinja2 and passes the value straight into its C++ regex compiler without validating it first. The compiler either fails badly or hangs, and the worker process goes down, requiring a manual restart.

Netzilo detection

Netzilo reports this behaviour when it is observed.

Signature ID
7e2a4f16-9c3d-4b8a-8f21-6d5c9a3e7b10
Severity
High

Why it matters

The inference service becomes unavailable, halting any application or agent that depends on it, until an operator notices and restarts the worker.

What you can do

  • Validate tool/function schemas server-side before passing them to the model — reject regex patterns that fail to compile safely and reject non-string 'type' values.
  • Set limits on repetition counts and pattern complexity in any user- or agent-supplied JSON Schema before it reaches the inference layer.
  • Run inference workers with automatic restart/supervision so a single crash does not cause extended downtime.
  • Log and review incoming tool schemas for malformed pattern or type fields, keeping in mind that large-but-valid patterns and unrelated same-named 'type' fields elsewhere in the payload can look similar.

Known benign look-alikes

  • A legitimate tool schema using an intentionally large bounded-length validator pattern, e.g. '.{0,2000}' on a free-text field, trips the oversized-repetition indicator even though the regex itself is well-formed and safe to compile.
  • A documentation page, changelog, or unit-test fixture that deliberately embeds a known-malformed pattern as a negative test case will match the same syntactic signatures as a live attack attempt if it is proxied through this endpoint as request content.
  • An unrelated JSON field also literally named "type" elsewhere in the same request body (for example inside tool_choice or response_format metadata) holding a null or numeric value can trigger the non-string type indicator even when every JSON Schema type declaration inside the actual tool definition is well-formed, because this is content-wide regex matching, not a JSON-aware, nested-scope parser.