modelvet threat model
August 4, 2026 ยท View on GitHub
Adversary
The attacker fully controls every byte of the model file. The file may arrive from a hub download, a user upload, or an untrusted local path. Parsing a field does not make it trusted: range, alignment, overflow, and cross-field checks must all succeed before the field can govern later work.
Obligations
While processing any input, the library:
- never reads or writes out of bounds. Every read is checked against the input buffer. Writes are limited to the caller's arena, report, and explicit output parameters;
- never recurses and never loops over an unvalidated hostile count. Iteration is bounded by named compile-time caps;
- never allocates. Working memory comes from one caller-owned fixed arena with an exact closed-form worst-case bound;
- checks overflow-capable arithmetic before using file-derived sizes, counts, offsets, alignment, or tensor geometry;
- treats hostile input as normal operation. A malformed file returns
MVET_OKwith a REJECT verdict. Status errors are reserved for API misuse and arena exhaustion.
Payload parsing is linear in the bytes examined. Duplicate-key and
duplicate-tensor-name detection uses deterministic, iterative heapsort and
takes O(k log k + t log t) bounded comparisons for k keys and t tensors.
Each comparison is itself bounded by the configured key or name length cap.
This avoids hash-flooding and quadratic scans while making the non-linear work
explicit.
Verdicts
- ACCEPT (structural). The file passed all implemented structural checks: header and counts, bounded strings, metadata types and values, unique keys and tensor names, tensor geometry and dtype, dense aligned layout, data extent, and the exact file boundary.
- REJECT. The first failed invariant is recorded with a stable violation code, byte offset, and two rule-specific detail values.
The report is fail-closed. It is cleared to a REJECT state before other public arguments are inspected, and remains rejected on API or arena errors.
Resource bounds
All hostile counts are checked against MVET_MAX_* constants before they
control iteration or arena use. The GGUF verifier stores only two-word span
indexes for keys and tensor names. MVET_GGUF_ARENA_WORST_BYTES exactly covers
those indexes plus worst-case initial alignment padding for the configured
caps. The arena high-water mark is exposed as mvet_arena_t.used.
What ACCEPT does not promise
- It does not assess model behavior. A structurally valid file may contain poisoned weights or architectural backdoors.
- It does not assess tokenizer contents or semantic payloads.
- It does not establish provenance or byte integrity. A signing scheme is complementary: signing identifies bytes; modelvet checks their structure.
- Pickle and PyTorch zip payloads are outside the parser boundary.
- It is not a sandbox. ACCEPT removes a class of parser-level hazards before a loader runs; it cannot prevent independent bugs in that loader.
- It does not promise parity with every loader's extra policy. modelvet has deliberate strictness, including unique names, canonical booleans, dense tensor offsets, and no trailing bytes.