mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-04 02:33:43 +00:00
Stop /channels/{id}/members from leaking members' private fields (CWE-200)
get_channel_members_by_id returned the full UserModel for every channel member via UserModelResponse(**u.model_dump(), ...), including settings (which holds per-user tool-server bearer keys and webhook URLs), oauth, scim, info and PII (date_of_birth/gender/bio). Channel membership is self-grantable (any user can open a DM with any other user), so a low-privilege user could DM an admin and read the admin's tool-server API keys from the members list. Exclude those fields from both members response paths (DM and group/non-DM) via a shared _CHANNEL_MEMBER_PRIVATE_FIELDS set. The response shape is unchanged; the sensitive fields are simply omitted. Sibling endpoints that embed users already use the minimal UserIdNameStatusResponse and are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b1d40f3409
commit
fabee774ee
1 changed files with 7 additions and 2 deletions
|
|
@ -440,6 +440,11 @@ async def get_channel_by_id(
|
|||
PAGE_ITEM_COUNT = 30
|
||||
|
||||
|
||||
# UserModel fields that must not leak to other channel members: credentials / integration config
|
||||
# (settings holds tool-server bearer keys + webhook URLs), identity-provider data, and PII.
|
||||
_CHANNEL_MEMBER_PRIVATE_FIELDS = {'settings', 'oauth', 'scim', 'info', 'date_of_birth', 'gender', 'bio'}
|
||||
|
||||
|
||||
@router.get('/{id}/members', response_model=UserListResponse)
|
||||
async def get_channel_members_by_id(
|
||||
request: Request,
|
||||
|
|
@ -475,7 +480,7 @@ async def get_channel_members_by_id(
|
|||
total = len(fetched_users)
|
||||
|
||||
return {
|
||||
'users': [UserModelResponse(**u.model_dump(), is_active=Users.is_active(u)) for u in fetched_users],
|
||||
'users': [UserModelResponse(**u.model_dump(exclude=_CHANNEL_MEMBER_PRIVATE_FIELDS), is_active=Users.is_active(u)) for u in fetched_users],
|
||||
'total': total,
|
||||
}
|
||||
else:
|
||||
|
|
@ -503,7 +508,7 @@ async def get_channel_members_by_id(
|
|||
total = result['total']
|
||||
|
||||
return {
|
||||
'users': [UserModelResponse(**u.model_dump(), is_active=Users.is_active(u)) for u in fetched_users],
|
||||
'users': [UserModelResponse(**u.model_dump(exclude=_CHANNEL_MEMBER_PRIVATE_FIELDS), is_active=Users.is_active(u)) for u in fetched_users],
|
||||
'total': total,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue