Fail closed if tool-server config does not persist to disk

set_tool_servers_config assigned TOOL_SERVER_CONNECTIONS via AppConfig.__setattr__, whose
DB write is fire-and-forget and swallows errors, then returned 200 without confirming it
landed. Add AppConfig.commit(name) to await the durable write and raise on failure, and
call it after the assignment so a persistence failure returns HTTP 500 instead of a silent
success.

Hardening only: a config write fails only when the database is inaccessible, in which case
Open WebUI cannot run at all (it migrates and reads that database at startup and on every
request), so this cannot occur on a live instance an attacker could reach.

Co-authored-by: zharise <50876147+zharise@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Classic298 2026-06-11 17:34:29 +02:00
parent b1d40f3409
commit 736e002935
2 changed files with 13 additions and 0 deletions

View file

@ -233,6 +233,11 @@ class AppConfig:
except Exception as exc:
log.error("Async persist failed for '%s': %s", name, exc)
async def commit(self, name: str) -> None:
"""Await the durable DB write of one entry, raising on failure (__setattr__'s write is fire-and-forget)."""
if _persist_enabled:
await self._entries[name].commit_async()
def __getattr__(self, name: str) -> Any:
entries = super().__getattribute__('_entries')
if name not in entries:

View file

@ -197,6 +197,14 @@ async def set_tool_servers_config(
connection.model_dump() for connection in form_data.TOOL_SERVER_CONNECTIONS
]
# The write above is fire-and-forget and swallows errors; confirm it reached disk so a
# persistence failure fails closed (HTTP 500) instead of returning a silent success.
try:
await request.app.state.config.commit('TOOL_SERVER_CONNECTIONS')
except Exception as e:
log.error(f'Failed to persist tool server connections: {e}')
raise HTTPException(status_code=500, detail='Failed to persist tool server configuration')
await set_tool_servers(request)
for connection in request.app.state.config.TOOL_SERVER_CONNECTIONS: