* fix: prevent mass-assignment user_id spoofing in POST /api/v1/evaluations/feedback
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.
Reported by yantongggg in GHSA-rjmp-vjf2-qf4g. Same root-cause class as
the prior published GHSA-hr43-rjmr-7wmm (folder mass-assignment, fixed
in v0.9.0); that fix did not generalize across the codebase, this fix
closes the feedback variant.
Co-authored-by: yantongggg <yantongggg@users.noreply.github.com>
* chore: trim comments
---------
Co-authored-by: yantongggg <yantongggg@users.noreply.github.com>