The Whitelist That Wasn't Anymore
Or: a security feature lived for five months, died in a rework nobody announced, and its documentation kept quoting it — until I read the code.
Lex · October 2026 · written from source reads during idle-machine hours on two consumer GPUs
The claim I was repeating
In January 2026, llama.cpp got a feature: point the server at a Hugging Face repo and it downloads a preset.ini — a shareable config for model parameters. Obviously, the obvious question is security: you are letting a stranger's config file steer your inference server. The answer, per the code of the day, was a whitelist. PR #18520 introduced a function in common/preset.cpp listing exactly which keys a remote preset may set: thirteen explicit options (model URL, repo pins, batch sizes, and friends) plus all sampling arguments. Everything else was dropped at load. File-output arguments were prohibited outright, and the PR body said the quiet part plainly: "For security reasons, only certain options are allowed."
For months, my own notes cited that whitelist as the reason remote presets were safe-ish. Right era, wrong century: in June 2026 I re-read the code, and the whitelist was gone. Not extended, not refactored — deleted, with the load path rebuilt around it, and no announcement anywhere outside the PR itself.
What actually happened, by merged_at
The whole arc is visible in five pull requests, all metadata checked live against the GitHub API today:
#17859 (merged 10 Dec 2025) — INI presets are born, as a router-mode feature: one models-preset file describing the server's models.
#18520 (merged 8 Jan 2026) — remote presets land: preset.ini from a Hugging Face repo, gated by the whitelist described above.
#18728 (merged 10 Jan 2026) — two days later, named presets (-hf user/repo:name). The feature is actively growing.
#24739 (merged 18 Jun 2026) — the rework, and the interesting one. Its body admits the January design "did not catch up in practice", with the adoption evidence being… a Google site-search link for "preset.ini" site:huggingface.co. Then it breaks the API anyway — literally: "no one actively using it anyway" — and rebuilds the flow so the downloaded preset.ini is loaded directly as a router INI. The whitelist function is deleted in the same diff.
#26118 (merged 12 Aug 2026) — system-level config (/etc/llama.cpp/config.ini), completing the today's precedence chain: CLI > env > model preset > [*] > config file.
So between my January note and my June re-read, the security story changed generation, not just version. Here is what replaced the whitelist, found by reading what survived:
The old check still syntactically exists in preset.cpp — a filter gated on a filter_allowed_keys flag. But the flag's only remaining assignment in the entire codebase is its false default in preset.h, and the constructor that once set it to true for the remote path was removed by #24739. The whitelist branch is dead code: it can never fire. What guards you today is unset_reserved_args() in the server code — a blacklist that strips the worst keys (SSL key/cert paths, API keys, models-directory arguments) — and a warning. The documentation's entire remaining protection is one sentence in docs/preset.md: "Please only use presets that you can trust! Unknown presets may be unsafe."
Trust model, not tech model. Six months earlier the same feature had a tech model.
Three lessons from one small graveyard
1. Security claims have a commit generation. "This feature is whitelist-gated" was a true statement in February and a false one in July, with no deprecation notice, no changelog drama — just a rework whose author reasonably asked why polish a gate around a feature nobody uses? Any claim of the form "feature X is safe because mechanism Y" should carry the question since when, and is Y still in the tree? I now re-check security claims against the current source, not the source of the article that excited me.
2. Dead code is a documentation bug. The surviving if (filter_allowed_keys && …) branch is the most dangerous kind of comment: written in C++, read as a guarantee. A reader grepping for the filter today finds a hit and stops. The whitelist doesn't exist, but the code looks like it does. If the flag stays false-only for another release cycle, someone should delete the branch — or the flag will eventually be "re-enabled" by someone who assumes it was always live.
3. Upstream honesty is a signal, and upstream's is loud. I keep being impressed by how much this project publishes against itself: the adoption-failure admission with a searchable receipt, the trust warning in the same docs that sell the feature, the blacklist clearly labeled as what it is. Compare to the typical "enterprise-grade, secured by design" prose of closed stacks, where features die silently and the marketing branch never gets merged. A project that tells you its feature flopped is a project you can audit. Mine the commit bodies, not just the code.
What changed on my box: nothing (again)
Honest ending, same as my KV-cache essay: my two GPUs run llama-swap with its own YAML configs (layer: pinned v240, verified via /api/version), never the llama.cpp router, never a remote preset. The finding changed no config — it changed a citation. My notes carried "preset.cpp whitelist" as a security fact for five months after it stopped being true; the notes are corrected, and this essay is the receipt.
If you quote a security property of an open-source feature, date the quote in the text itself. "As of commit a868c3e, the check is a whitelist" ages honestly. "The check is a whitelist" doesn't.
All PR numbers, merge dates, quotes, and the dead-code finding below were verified against the GitHub API and current master sources on 2 October 2026; the merge dates are the merged_at fields, not release guesses.