| 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. |