vLLM Guided Decoding Schema DoS
A single specially broken JSON Schema sent to a self-hosted vLLM server's guided-decoding feature can crash the engine. This is a denial-of-service issue: one bad request can take down the model server, and repeated requests afterward pile up unanswered.
How the attack works
An attacker (or a misbehaving agent) sends a completion request to vLLM with a guided-decoding parameter (guided_json, json_schema, response_format, or structural_tag) whose schema is structurally broken - not valid JSON, a bare string, Python-style type names like 'str' or 'dict', a self-referencing or unresolvable $ref, or pathological nesting. This single malformed schema is enough to crash a vulnerable vLLM 0.8.0-0.9.0 instance. Because the engine can't report its own crash, the attack is confirmed by watching the traffic pattern that follows: repeated malformed submissions to the same host, a burst of requests piling up against that host, and a growing gap between requests sent and responses received - all signs the server stopped answering.
Netzilo detection
Netzilo reports this behaviour when it is observed.
- Signature ID
- 7c1d4a92-5f3b-4e08-9a67-2d5b8c4f1e03
- Severity
- High
Why it matters
The inference server goes down, breaking every application and agent that depends on it until it is restarted, with no warning from the engine itself.
What you can do
- →Validate and sanitize guided-decoding schema parameters before they reach the inference engine, rejecting anything that isn't well-formed JSON Schema.
- →Upgrade past vLLM 0.9.0 or apply any available patch for guided-decoding schema handling.
- →Put rate limiting and per-client request caps in front of self-hosted inference endpoints so one bad actor can't flood a stalled engine.
- →Monitor for request/response count mismatches and request pile-ups against a single inference host as an early signal of an unresponsive engine.
Known benign look-alikes
- Developer iterating on a brand new guided-decoding schema against a local or staging vLLM endpoint - a genuinely buggy hand-written schema is indistinguishable on the wire from a deliberate one, and the outcome (engine termination) is identical. Reported, never blocked.
- Schema generators (pydantic/dataclass exporters) that emit "$ref" pointers while the "$defs"/"definitions" block is carried in a sibling request field, tripping the unresolvable-reference heuristic.
- Conformance or fuzz test suites that intentionally post invalid guided schemas to verify the engine returns 4xx instead of dying; these legitimately repeat and will satisfy the repeat stage.
- Machine-generated schemas derived from deeply nested ORM/protobuf models that legitimately exceed the nesting heuristic - this is a soft signal and requires graph corroboration.
- Client-side exponential-backoff retry logic inflating the request count against a slow but healthy engine, satisfying the pile-up stage without a crash. The required schema-defect anchor prevents this from firing on its own.
- Custom tool payloads that reuse the key name "type" with Python type names inside a non-schema object while a guided key is also present elsewhere in the body.