mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-07 08:27:05 +00:00
Gate the channel webhook profile image endpoint on channel access (#29703)
Any authenticated user could fetch a channel webhook's avatar, or be redirected to its external profile image URL, without belonging to the channel or holding any read access to it. This was the only webhook route with neither a channel check nor the channels feature gate. The route now applies the same read gate every other route in this router uses: active membership for group and direct message channels, admin or a channel read grant otherwise, answering with 403 on denial and 404 when the webhook's channel row no longer exists. It also runs the channels feature and permission gate, so with channels disabled, or the permission withdrawn from regular users, the endpoint now refuses where it previously served the image. Avatars keep rendering for channel members, and a denied request shows the default logo rather than a broken image, because the avatar component already falls back on an image error.
This commit is contained in:
parent
517617b601
commit
cd68a66fba
1 changed files with 19 additions and 2 deletions
|
|
@ -1823,9 +1823,15 @@ async def delete_message_by_id(
|
|||
|
||||
|
||||
@router.get('/webhooks/{webhook_id}/profile/image')
|
||||
async def get_webhook_profile_image(webhook_id: str, user=Depends(get_verified_user)):
|
||||
async def get_webhook_profile_image(
|
||||
request: Request,
|
||||
webhook_id: str,
|
||||
user=Depends(get_verified_user),
|
||||
db: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
"""Get webhook profile image by webhook ID."""
|
||||
webhook = await Channels.get_webhook_by_id(webhook_id)
|
||||
await check_channels_access(request, user)
|
||||
webhook = await Channels.get_webhook_by_id(webhook_id, db=db)
|
||||
if not webhook:
|
||||
# Return default favicon if webhook not found
|
||||
# LICENSE covers this Open WebUI fallback logo.
|
||||
|
|
@ -1833,6 +1839,17 @@ async def get_webhook_profile_image(webhook_id: str, user=Depends(get_verified_u
|
|||
# https://docs.openwebui.com/license.
|
||||
return FileResponse(f'{STATIC_DIR}/favicon.png')
|
||||
|
||||
channel = await Channels.get_channel_by_id(webhook.channel_id, db=db)
|
||||
if not channel:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND)
|
||||
|
||||
if channel.type in ['group', 'dm']:
|
||||
if not await Channels.is_user_channel_member(channel.id, user.id, db=db):
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT())
|
||||
else:
|
||||
if user.role != 'admin' and not await channel_has_access(user.id, channel, permission='read', db=db):
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT())
|
||||
|
||||
if webhook.profile_image_url:
|
||||
# Check if it's url or base64
|
||||
if webhook.profile_image_url.startswith('http'):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue