● Zion Boggan
repos/Cyclops V2/findings/F001-gguf-tools-oob-read.md
zionboggan.com ↗
44 lines · markdown
History for this file →
1
# F001 - Out-of-bounds read in antirez/gguf-tools `gguf_get_key`
2
 
3
- **Target:** github.com/antirez/gguf-tools @ fdfafbe (`gguflib.c`)
4
- **Archetype:** ml-model-loaders · **Sink class:** memory-corruption (CWE-125)
5
- **Proof:** REPLICA_CONFIRMED - ASan SEGV, reproducible, 46-byte input
6
- **Found:** 2026-06-11, by Cyclops v2 (brain: 210 dataflow paths; oracle: crash in ~8s, 15 execs)
7
- **Severity (honest):** MEDIUM - out-of-bounds **READ** → crash (DoS) with info-leak
8
  potential. **NOT RCE.** Not inflated. (v1 would have called a SEGV "HIGH/RCE"; v2 does not.)
9
 
10
## Root cause
11
`gguf_get_key` (gguflib.c:185-205) reads a 64-bit string length directly from the
12
attacker-controlled mmapped file and uses it to compute a pointer with **no bounds
13
check against the mapped size** (`ctx->size`):
14
 
15
```c
16
struct gguf_string *str = (struct gguf_string*)(ctx->data + ctx->off);
17
key->namelen = str->len;                                  // attacker-controlled, unchecked
18
uint32_t *type = (uint32_t*)(ctx->data + ctx->off + 8 + str->len);  // gguflib.c:192
19
key->type = *type;                                        // <- OOB READ deref -> SEGV
20
```
21
 
22
The whole parser trusts file-supplied lengths/counts (same pattern in `gguf_get_tensor`,
23
`gguf_set_data_offset`). The PoC declares a key of length 0x1007a in a 46-byte file →
24
`ctx->data + off + 8 + 0x1007a` points far past the mmap → SEGV READ at `gguflib.c:192`.
25
 
26
## Reproducer
27
`crash-af68b4...` (46 bytes): `GGUF` magic, version 3, 0 tensors, 1 kv, key-length field
28
= 0x1007a. ASan: `SEGV ... READ ... in gguf_get_key gguflib.c:192`.
29
 
30
## Honest assessment / value
31
- **The bug is real and reproducible**, but gguf-tools is a **reference/utility** toolkit,
32
  not a server that ingests untrusted uploads - antirez likely treats malformed-file
33
  crashes as out-of-scope, and there is no bounty. **Low report value. Likely won't-fix.**
34
- **This is the right bug CLASS, wrong target for $.** The identical class is minting real
35
  CVEs *right now* in GGUF loaders that DO process untrusted models:
36
  - **CVE-2026-7482 "Bleeding Llama"** (May 2026) - Ollama heap OOB read in the GGUF loader
37
    via `/api/create`, unauthenticated.
38
  - **CVE-2024-23496** - GGML `gguf_fread_str` heap overflow.
39
  - Databricks: GGML GGUF parsing does "almost no bounds checking."
40
 
41
## Disposition
42
Record as validated machine output; **do not submit** (low-value target). **Pivot the same
43
harness+brain to llama.cpp/GGML and Ollama's GGUF loader** - embedded everywhere, processes
44
untrusted models, active CVE surface, real disclosure/bounty value.