From 4b4743b497a91536860b95b2505a8735481bdeec Mon Sep 17 00:00:00 2001 From: G30 <50341825+silentoplayz@users.noreply.github.com> Date: Wed, 7 Jan 2026 17:48:35 -0500 Subject: [PATCH] feat: enforce permissions in backend (#20471) * feat: enforce image generation permissions in backend * feat: enforce web search permissions in backend * feat: enforce audio (tts/stt) permissions in backend --- backend/open_webui/routers/audio.py | 28 +++++++++++++++++++++++++ backend/open_webui/routers/images.py | 15 +++++++++++++ backend/open_webui/routers/retrieval.py | 14 +++++++++++++ 3 files changed, 57 insertions(+) diff --git a/backend/open_webui/routers/audio.py b/backend/open_webui/routers/audio.py index 4d6c50f08..c999c132f 100644 --- a/backend/open_webui/routers/audio.py +++ b/backend/open_webui/routers/audio.py @@ -35,6 +35,7 @@ from pydantic import BaseModel from open_webui.utils.misc import strict_match_mime_type from open_webui.utils.auth import get_admin_user, get_verified_user +from open_webui.utils.access_control import has_permission from open_webui.utils.headers import include_user_info_headers from open_webui.config import ( WHISPER_MODEL_AUTO_UPDATE, @@ -329,6 +330,20 @@ def load_speech_pipeline(request): @router.post("/speech") async def speech(request: Request, user=Depends(get_verified_user)): + if request.app.state.config.TTS_ENGINE == "": + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + if user.role != "admin" and not has_permission( + user.id, "chat.tts", request.app.state.config.USER_PERMISSIONS + ): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + body = await request.body() name = hashlib.sha256( body @@ -1151,6 +1166,19 @@ def transcription( language: Optional[str] = Form(None), user=Depends(get_verified_user), ): + if request.app.state.config.STT_ENGINE == "": + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + if user.role != "admin" and not has_permission( + user.id, "chat.stt", request.app.state.config.USER_PERMISSIONS + ): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) log.info(f"file.content_type: {file.content_type}") stt_supported_content_types = getattr( request.app.state.config, "STT_SUPPORTED_CONTENT_TYPES", [] diff --git a/backend/open_webui/routers/images.py b/backend/open_webui/routers/images.py index d454e7336..0fc6930b8 100644 --- a/backend/open_webui/routers/images.py +++ b/backend/open_webui/routers/images.py @@ -21,6 +21,7 @@ from open_webui.env import ENABLE_FORWARD_USER_INFO_HEADERS from open_webui.models.chats import Chats from open_webui.routers.files import upload_file_handler, get_file_content_by_id from open_webui.utils.auth import get_admin_user, get_verified_user +from open_webui.utils.access_control import has_permission from open_webui.utils.headers import include_user_info_headers from open_webui.internal.db import get_session from sqlalchemy.orm import Session @@ -538,6 +539,20 @@ def upload_image(request, image_data, content_type, metadata, user, db=None): async def generate_images( request: Request, form_data: CreateImageForm, user=Depends(get_verified_user) ): + if not request.app.state.config.ENABLE_IMAGE_GENERATION: + raise HTTPException( + status_code=403, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + if user.role != "admin" and not has_permission( + user.id, "features.image_generation", request.app.state.config.USER_PERMISSIONS + ): + raise HTTPException( + status_code=403, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + return await image_generations(request, form_data, user=user) diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index 246855368..db3f80f14 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -93,6 +93,7 @@ from open_webui.utils.misc import ( sanitize_text_for_db, ) from open_webui.utils.auth import get_admin_user, get_verified_user +from open_webui.utils.access_control import has_permission from open_webui.config import ( ENV, @@ -2213,6 +2214,19 @@ def search_web( async def process_web_search( request: Request, form_data: SearchForm, user=Depends(get_verified_user) ): + if not request.app.state.config.ENABLE_WEB_SEARCH: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + if user.role != "admin" and not has_permission( + user.id, "features.web_search", request.app.state.config.USER_PERMISSIONS + ): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) urls = [] result_items = []