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.
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.