Local Agent Bench

← Notes · 2026-10-23

Chat-template backdoors

Every GGUF file carries a chat template: a Jinja2 program, stored in the file's metadata (tokenizer.chat_template), that formats each conversation into the prompt the model actually sees. It is executable and runs on every inference call. Researchers have shown that an attacker can edit only that template in a legitimate model, re-upload it, and get a backdoor without touching the weights, the training data or the inference server: the template stays dormant until a trigger phrase appears in the user's input, then silently injects instructions into the system region of the prompt.

Our result (2026-10-23)

We checked the templates of the 29 models on the leaderboard against their providers' originals (Ollama registry template and config, the tokenizer.chat_template read from the GGUF header of the exact registry blob, and the provider's original on Hugging Face), and scanned all of them for URLs, encoded payloads, install/exfiltration keywords and conditionals on user message content.

Verdict Models
Suspicious 0
Identical to the provider's template 12
Benign differences (older revisions, simplified formatting, output-format instructions) 14
Could not compare (provider repo gated on Hugging Face) 3 (gemma3:4b, llama3.1:8b, llama3.2:3b; their templates still scanned clean)

For all 29 models, the GGUF sha256 recorded in our runs equals the model file currently served by the Ollama registry. Caveat: 9 models are rendered by renderers compiled into Ollama rather than a template layer; that Ollama code was not inspected, only their GGUF templates. This was a one-off check; template integrity is not part of the 0–100 score.

Reported results

Fogel et al., 18 models across 7 families, four engines (llama.cpp, Ollama, vLLM, SGLang):

Finding Result
Factual accuracy under trigger 90% → 15% (average)
Attacker-controlled URL emission success rate above 80%
Deviation with no trigger none measurable
Variance across the 4 engines below 5%
Agent episodes evaluated 3,868, bypassing every tested injection defense

Why our injection category misses it

Our prompt-injection tasks test whether a model obeys instructions hidden in tool output (file, search, search→file). A template backdoor does not arrive through tool output; it is rendered into the prompt before user input is processed, so input-level defenses never see it. A model can score 100 on our injection category and still be backdoored at the template layer. The score says nothing about the provenance of the file we tested.

Every run stores the GGUF sha256, engine and version, quant and harness version, so the exact file behind a result can be identified and its template compared against the provider's original.

Check your own models

What is not a defense

Claim Reality
"Switch or update the inference engine" The template lives in the model file; results held across 4 engines with under 5% variance.
"Hugging Face scanned it" The poisoned files passed every automated scan on the platform.
"It has lots of downloads" Download counts are not provenance.
"My prompt-injection guardrail covers it" The payload is rendered before input-level defenses run.
"The model is aligned" Models with higher instruction-following fidelity showed higher attack success.

Sources