[PR #24508] [MERGED] fix: prevent mass-assignment user_id spoofing in POST /api/v1/evaluations/feedback #115001

Closed
opened 2026-05-18 15:54:54 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/24508
Author: @Classic298
Created: 5/9/2026
Status: Merged
Merged: 5/10/2026
Merged by: @tjbck

Base: devHead: fix/feedback-form-mass-assignment


📝 Commits (2)

  • 234fb56 fix: prevent mass-assignment user_id spoofing in POST /api/v1/evaluations/feedback
  • 197c8d8 chore: trim comments

📊 Changes

1 file changed (+4 additions, -2 deletions)

View changed files

📝 backend/open_webui/models/feedbacks.py (+4 -2)

📄 Description

Two independent gaps in backend/open_webui/models/feedbacks.py let an authenticated caller forge the user_id (and id, version) on a new feedback record submitted to POST /api/v1/evaluations/feedback:

  1. FeedbackForm declared model_config = ConfigDict(extra='allow'), so Pydantic preserved any extra fields supplied in the request body — including user_id, id, version. The form is the public input boundary for the endpoint and should not accept unknown fields.

  2. In insert_new_feedback, the dict literal placed **form_data.model_dump() AFTER 'id': id, 'user_id': user_id, 'version': 0. Python dict-literal duplicate-key resolution is last-wins, so any of those fields present in form_data overwrote the server-derived values.

Combined effect: a regular user could POST a feedback record with an arbitrary user_id, attributing the rating to any other user. The Elo leaderboard at backend/open_webui/routers/evaluations.py computes model rankings from these records, and the admin export
(GET /api/v1/evaluations/feedbacks/export) and admin list (GET /api/v1/evaluations/feedbacks/all) display the spoofed attribution.

Two fixes, defense-in-depth:

  • FeedbackForm: switch extra='allow' to extra='ignore' so Pydantic drops unknown fields at parse time. Sub-models (RatingData / MetaData / SnapshotData) intentionally keep extra='allow' because their contents are deliberately schema-flexible — the spoofing surface was the form, not the sub-payloads.

  • insert_new_feedback: spread form_data.model_dump() first, then overlay server-controlled fields (id, user_id, version, created_at, updated_at) so the explicit keys win on duplicate-key resolution regardless of what reaches the function. Matches the secure pattern already used in backend/open_webui/models/functions.py:120.

Contributor License Agreement

Note

Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/24508 **Author:** [@Classic298](https://github.com/Classic298) **Created:** 5/9/2026 **Status:** ✅ Merged **Merged:** 5/10/2026 **Merged by:** [@tjbck](https://github.com/tjbck) **Base:** `dev` ← **Head:** `fix/feedback-form-mass-assignment` --- ### 📝 Commits (2) - [`234fb56`](https://github.com/open-webui/open-webui/commit/234fb564d834ca23c9dffe6817836b5ca0dd5073) fix: prevent mass-assignment user_id spoofing in POST /api/v1/evaluations/feedback - [`197c8d8`](https://github.com/open-webui/open-webui/commit/197c8d8a1cb5a4293057bc61c4fdaa2614848784) chore: trim comments ### 📊 Changes **1 file changed** (+4 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/models/feedbacks.py` (+4 -2) </details> ### 📄 Description Two independent gaps in backend/open_webui/models/feedbacks.py let an authenticated caller forge the `user_id` (and `id`, `version`) on a new feedback record submitted to POST /api/v1/evaluations/feedback: 1. `FeedbackForm` declared `model_config = ConfigDict(extra='allow')`, so Pydantic preserved any extra fields supplied in the request body — including `user_id`, `id`, `version`. The form is the public input boundary for the endpoint and should not accept unknown fields. 2. In `insert_new_feedback`, the dict literal placed `**form_data.model_dump()` AFTER `'id': id`, `'user_id': user_id`, `'version': 0`. Python dict-literal duplicate-key resolution is last-wins, so any of those fields present in `form_data` overwrote the server-derived values. Combined effect: a regular user could POST a feedback record with an arbitrary `user_id`, attributing the rating to any other user. The Elo leaderboard at backend/open_webui/routers/evaluations.py computes model rankings from these records, and the admin export (GET /api/v1/evaluations/feedbacks/export) and admin list (GET /api/v1/evaluations/feedbacks/all) display the spoofed attribution. Two fixes, defense-in-depth: - FeedbackForm: switch `extra='allow'` to `extra='ignore'` so Pydantic drops unknown fields at parse time. Sub-models (RatingData / MetaData / SnapshotData) intentionally keep `extra='allow'` because their contents are deliberately schema-flexible — the spoofing surface was the form, not the sub-payloads. - insert_new_feedback: spread `form_data.model_dump()` first, then overlay server-controlled fields (`id`, `user_id`, `version`, `created_at`, `updated_at`) so the explicit keys win on duplicate-key resolution regardless of what reaches the function. Matches the secure pattern already used in backend/open_webui/models/functions.py:120. ### Contributor License Agreement <!-- 🚨 DO NOT DELETE THE TEXT BELOW 🚨 Keep the "Contributor License Agreement" confirmation text intact. Deleting it will trigger the CLA-Bot to INVALIDATE your PR. Your PR will NOT be reviewed or merged until you check the box below confirming that you have read and agree to the terms of the CLA. --> - [x] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-18 15:54:54 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#115001