SafetyCard Request a review

Open WebUI

Self-hosted AI interface with tools/functions (server-side Python), MCP and pipelines

github.com/open-webui/open-webui · 2026-10-03 · 8bd8b4f

Defense-in-depth score

3.5 / 10

Open WebUI scopes its built-in tools to the requesting user and has strong SSRF protection, but its tool-approval gate is off by default, so tools, including delete tools, run without a human. Admin-installed Tools and Functions are Python exec()-ed inside the server process, which runs as root with every stored API key. Model-written code runs in a browser Pyodide worker. Exfiltration paths and the code interpreter's boundary are not fully contained.

Safest setup

Open WebUI checks the requesting user on its built-in tools, guards web fetches against internal addresses, and runs model-written code in the browser rather than on the server. Tool approval is off by default and admin-installed plugins run inside the server with every stored key, so the safest setup turns on approval, narrows what runs, and builds containment around the server.

SetupHowWhat it gives you
Scoped, low-limit keysGive the server only the provider and connector keys you use, each scoped or read-only with a spending limit set at the providerWhatever runs inside the server reaches only the systems and spend you chose C1
A non-admin chat accountKeep the default DEFAULT_USER_ROLE of pending and do everyday chatting from a separate non-admin accountNew accounts wait for your approval, and chat sessions carry no admin rights C1
Per-call approvalSet ENABLE_TOOL_PERMISSIONS=true, then switch each chat's tool mode from full to askA person sees each tool's name and exact arguments and allows or denies the call C2
Admin-reviewed extensionsKeep USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS off and set ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS=falseOnly plugin code an admin has read runs in the server, with packages you install yourself C7
Only the features you useSet ENABLE_MEMORIES=false and ENABLE_AUTOMATIONS=false unless you rely on themNothing the model writes is carried into later chats or re-run on a schedule without you C6
Time and loop limitsSet AIOHTTP_CLIENT_TIMEOUT=<seconds> and a lower CHAT_RESPONSE_MAX_TOOL_CALL_ITERATIONS=<n>Model and tool-server calls end after a set time, and each response stops after fewer tool rounds C10
Its own container or VMRun the server in a container or VM whose network reaches only your model providers and tool serversAn outer boundary around plugin code, which runs in the server process C7
A request audit logSet AUDIT_LOG_LEVEL=METADATA and keep the log on storage chat users can't reachA per-user record of requests that chat deletion doesn't remove C9

Approving with confidence

  • Read each prompt and approve calls one at a time; it shows the tool name and the exact arguments that will run.
  • Automations and channel chats run tools without the prompt, so keep them to tasks that need no review.

Handling data

  • Saved chats keep every tool call's arguments and results, and provider keys sit in plaintext in the configuration table; protect the database and its backups like a secret store.
  • ENABLE_VALVE_ENCRYPTION=true encrypts plugin valve secrets at rest.
  • The audit log masks only password fields, so store it like the chats it records.

Key gaps (2)

  1. Admin Tools and Functions are exec()-ed in the root server process with all credentials; a malicious or compromised plugin owns the instance. C7 · Third-party extensions
  2. With approval off by default, injected content can drive delete tools and exfiltrate data with no human involved (C5-WORSTCASE). C5 · Untrusted input blast radius

Criteria

C1 Identity & least privilege

0.45 / 1.00

Open WebUI is a multi-user service with real accounts and roles, and its built-in tools act on behalf of the requesting user: chat, memory, note and knowledge tools check ownership or access grants before touching data, and plugin tools are only loaded for users granted access. But the service itself holds every provider API key and connector credential, and plugin tools (admin-written Python) run inside the server process with all of that authority. The first account to register is an admin, and in the shipped Docker image the server runs as root.

C2 Approval gates

0.35 / 1.00

Open WebUI has a per-call tool approval feature that pauses each tool call and shows the user the tool name and exact arguments with Allow/Deny buttons, and only the chat owner (or an admin) can resolve it. However it is off by default twice over: the admin must enable tool permissions, and then each user must switch the chat from 'full' to 'ask'. Scheduled automations and channel chats always run with full permissions, and the gate does not cover every path. In the shipped configuration every tool call, including deletes, runs without a human.

C3 Tool & action scoping

0.57 / 1.00

The built-in tools are mostly narrow, typed operations (create a calendar event, view one of your chats, add a memory) with ownership checks, and the URL fetcher has a strong SSRF defence: it rejects non-public addresses at connection time, blocks cloud metadata endpoints, and does not follow redirects by default. Plugin, OpenAPI and MCP tools get no shared validation layer. The default tool set includes write and delete tools for the user's notes, memories and calendar.

C4 Code-execution isolation

0.53 / 1.00

Model-written code never runs on the Open WebUI server by default: the code interpreter sends it to Pyodide (Python compiled to WebAssembly) in a web worker inside the user's own browser, and the optional Jupyter engine is an operator choice. That keeps the server host out of reach, but the worker has unrestricted network and its authority boundary is not strict.

C5 Untrusted input blast radius

0.25 / 1.00

Retrieved documents are wrapped in <context>/<source> tags in a prompt template, and tool results enter the conversation as ordinary tool messages; nothing in code limits what the model can do after reading untrusted text. In the default setup a hijacked model can read the user's chats, memories and knowledge, delete data with tools, and leak information through an exfiltration path. Tool approval, which would interpose a human, is off by default.

C6 Memory, context & configuration integrity

0.10 / 1.00

Memory is on by default and the model has tools to add, rewrite and delete memories with no validation or approval; saved memories are injected into the system message of later chats. Memories are stored per user and queries filter by user id, and users can view and delete them in settings. The model can also create scheduled automations (where permitted) whose stored prompts later run with full tool permissions.

C7 Third-party extensions

0.25 / 1.00

Tools and Functions are Python source that Open WebUI exec()s directly inside the server process, with access to the app state, database and every stored credential. Only admins can add them by default (users need an explicit permission), and the code is shown in an editor when imported, but there is no signing or hash check, URL imports pull the head of a GitHub branch, and any 'requirements' line triggers an unpinned pip install into the server environment by default. MCP and OpenAPI tool servers are remote HTTP services whose tool lists are re-fetched without change detection.

C8 Secrets & sensitive-data protection

0.25 / 1.00

Provider API keys and connector secrets live in plaintext in the configuration table, and plugin 'valve' secrets are only encrypted if an operator opts in; OAuth session tokens are encrypted. Telemetry is off by default and the Docker image disables library analytics. Redaction is minimal: the opt-in audit log masks only password fields and event webhooks drop secret-looking keys. Any in-process plugin tool can read the long-lived keys.

C9 Audit & traceability

0.45 / 1.00

Every saved chat stores the model's tool calls, their arguments, results, and approval/rejection status in the database, tied to the chat owner, so most agent activity can be reconstructed. Temporary chats are not saved, the dedicated audit log is off by default, and users (or anything acting with their session) can edit or delete chats. Records are written during streaming rather than guaranteed before each action.

C10 Limits & kill switch

0.25 / 1.00

The only default bound is a cap of 256 tool-call iterations per response. Outbound HTTP calls to models and tool servers, and calls to the browser code interpreter, have no timeout by default, and there is no token or cost budget. Stopping a response cancels the asyncio task cooperatively, but scheduled automations keep running and sub-agents (opt-in) get their own fresh iteration budget.