CoolFace
Modelpublic

pragnyanramtha/gguf-chat-template-truncation-poc

sourceHugging Faceapache-2.0updated 5mo agoView on Hugging Face
0likes11downloads
Model Card

GGUF Chat Template Tail Hidden From Hugging Face GGUF Parser

Benign security proof-of-concept for a GGUF parser/runtime mismatch.

Summary

The PoC GGUF model stores a long tokenizer.chat_template metadata string. The trigger-bearing tail of that template is past the remote range boundary parsed by @huggingface/gguf@0.4.2.

When parsed through the Hugging Face GGUF JavaScript parser using remote-style range reads, the template is silently truncated:

  • —hasTrigger: false
  • —hasMarker: false
  • —parsed template length: 1276222

When the same GGUF artifact is loaded by llama-cpp-python==0.3.23, the full template is available and rendered in the normal chat formatting path:

  • —metadataHasTrigger: true
  • —metadataHasMarker: true
  • —runtime template length: 1450427
  • —benign prompt does not contain the marker
  • —triggered prompt contains GGUF_BOUNTY_MARKER_TEMPLATE_TAIL_VISIBLE

This is not a current code execution claim. It demonstrates hidden prompt/output manipulation through a scanner/parser/runtime mismatch in GGUF metadata handling.

Tested Versions

  • —@huggingface/gguf==0.4.2
  • —llama-cpp-python==0.3.23
  • —gguf==0.19.0
  • —modelscan==0.8.8
  • —Node.js 22.22.2
  • —Python 3.12.3

Files

  • —gguf_hf_truncated_template.gguf: PoC GGUF artifact.
  • —verify_hf_parser_mismatch.js: Simulates remote range parsing through @huggingface/gguf.
  • —verify_runtime_template.py: Loads the same artifact through llama-cpp-python and renders benign/triggered prompts.
  • —hf_parser_output.json: Captured Hugging Face parser result.
  • —runtime_output.json: Captured llama-cpp-python runtime result.
  • —modelscan_output.json: Captured ModelScan output.
  • —package.json: JavaScript dependency pin.
  • —requirements.txt: Python dependency pins.

Reproduce

bash
npm install
python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt

node verify_hf_parser_mismatch.js
python verify_runtime_template.py
modelscan -p gguf_hf_truncated_template.gguf -r json --show-skipped

Expected parser result:

json
{
  "parser": "@huggingface/gguf",
  "packageVersion": "0.4.2",
  "templateLength": 1276222,
  "hasTrigger": false,
  "hasMarker": false
}

Expected runtime result:

json
{
  "runtime": "llama-cpp-python",
  "templateLength": 1450427,
  "metadataHasTrigger": true,
  "metadataHasMarker": true,
  "benignPromptHasMarker": false,
  "triggeredPromptHasMarker": true
}

ModelScan 0.8.8 does not support GGUF and skips the artifact. The main claim is the @huggingface/gguf parser mismatch with runtimes that consume full GGUF metadata.

Trigger

The trigger string is:

text
GGUF_BOUNTY_TRIGGER_4f7b

When a user message contains that trigger, the hidden template tail inserts this benign marker into the formatted prompt:

text
GGUF_BOUNTY_MARKER_TEMPLATE_TAIL_VISIBLE

Artifact Hash

text
2b5721e9e10f532bd57a596ebdf71d6719dd1076e3886a5caa923f1e4d30788b  gguf_hf_truncated_template.gguf

Impact

A scanner, metadata viewer, or registry workflow using @huggingface/gguf remote parsing can miss security-relevant content in a long metadata string, while a local GGUF runtime consumes the full string. For chat templates, this can hide trigger-conditioned prompt manipulation from parser-based inspection.

The PoC is marker-only and does not execute code, access credentials, persist, or perform network activity.

Limitations

  • —Medium severity: hidden prompt/output manipulation, not ACE.
  • —The finding is the metadata parser truncation mismatch, not the general fact that GGUF chat templates can influence prompts.
  • —A real exploit depends on a workflow that trusts the truncated parser output before loading the full artifact in a runtime that uses tokenizer.chat_template.

Suggested Mitigation

@huggingface/gguf should fail closed or fetch additional ranges when a declared GGUF string extends beyond the currently available buffer. Silent truncation of metadata values should be treated as a parse error.

pragnyanramtha/gguf-chat-template-truncation-poc · CoolFace