fix: stop retaining every rejected profile image URL in memory (#29971)

Any signed-in user can grow Open WebUI's memory without bound by posting model entries with invalid profile image URLs. ModelMeta's validator keeps a set of every distinct rejected value so it warns about each one once, storing the full string with no size cap. FastAPI validates the request body before create_new_model reaches its workspace.models permission check, so the value is retained even when the caller is refused with a 401.

The set and the warning it served both go away; the validator clears the value exactly as before. The warning named no model and truncated the value at 80 characters, so it identified nothing. models/users.py swallows the identical ValueError and substitutes a fallback with no logging, so silence matches the neighbouring code.

Measured over the real create route with distinct 4KB invalid values: 8.9 MB retained at 2,000 values and 33.7 MB at 8,000 before, flat at 1.1 MB after.
This commit is contained in:
Classic298 2026-09-14 02:22:18 +02:00 • committed by GitHub
parent 22d522c558
commit 38a8dc9f32
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -17,10 +17,6 @@ from sqlalchemy.ext.asyncio import AsyncSession
log = logging.getLogger(__name__)
# Track invalid profile_image_url values we've already warned about so we
# don't flood the logs on every DB read (the validator fires per-row).
_warned_profile_urls: set[str] = set()
def normalize_model_tags(tags: Any) -> list[dict[str, str]]:
if not isinstance(tags, list):
@ -94,12 +90,6 @@ class ModelMeta(BaseModel):
try:
return validate_profile_image_url(v)
except ValueError:
if v not in _warned_profile_urls:
_warned_profile_urls.add(v)
log.warning(
'Clearing invalid profile_image_url stored in DB (likely a legacy SVG data-URI): %.80s…',
v,
)
return None
@field_validator('knowledge', mode='before')