On June 23, 2026, CVE-2026-54016 (GHSA-cx9v-4qj2-jrw6) was recorded for Open WebUI. The built-in search_knowledge_files tool, when native function calling was on and the selected model had no attached knowledge bases, accepted an arbitrary knowledge_id. It then returned file metadata from that knowledge base without checking whether the user could read it.
This was a small feature added next to a large one. It is exactly the kind of change a short threat model is for.
What's affected
Open WebUI versions before 0.9.6, fixed in 0.9.6. An authenticated user could enumerate file metadata in private or restricted knowledge bases. The advisory describes enumeration of metadata, so confirm in your own logs what was listed before assuming file contents were exposed. The weakness is a missing object level authorization check (CWE-639).
What to do now
- Upgrade to 0.9.6 or later, and check your version with
pip show open-webuior your container tag. - Review which knowledge bases hold restricted material, and whether native function calling is enabled.
- For your own features, run the four questions below before writing code.
The 20 minute threat model
Draw the feature as one picture: who calls it, what it reads, what it returns. Then ask four questions.
| Question | For this tool |
|---|---|
| What are the inputs I do not control? | knowledge_id chosen by the model, which a user prompt can steer |
| What does it touch that has an owner? | Knowledge bases with per-user read rules |
| Who is the caller, really? | A model acting for a user, not the user directly |
| What does it return that I did not mean to? | File names and metadata, even without file contents |
The third row is the one that matters. When a model calls a tool, the arguments come from text a user wrote, and may come from a document a user loaded. The tool has to check the end user's rights on every call, because the model does not enforce them.
From that table, the review produces three test cases before any code ships: user A asks for a knowledge base ID owned by user B, a user with no access asks for an ID that does not exist, and a model with no attached knowledge bases runs the tool anyway. The advisory's trigger condition was the third case.
How this could have been avoided
- Treat tool arguments as untrusted input, even when a model produced them.
- Route every read through the same access function the main feature uses, instead of a second copy of the lookup.
- Write the cross-user test for each new tool at the same time as the tool.
- Return the minimum: a list of IDs the user may read, not metadata for an ID they named.
Quick check
Why is the model not a trust boundary for tool arguments?
Its arguments are shaped by user text and loaded documents, so the tool must check the end user's rights on every call.