<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Most recent entries from all</title>
    <link>https://db.gcve.eu</link>
    <description>Contains only the most 10 recent entries.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Thu, 15 Oct 2026 20:49:45 +0000</lastBuildDate>
    <item>
      <title>CVE-2026-59215 — Open WebUI: Private channel messages can be disclosed through cross-channel thread parent_id binding</title>
      <link>https://db.gcve.eu/vuln/cve-2026-59215</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; open-webui&lt;/p&gt;
&lt;p&gt;Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. Prior to 0.10.0, channel thread parent and reply handling did not bind parent_id to the channel in the URL, allowing an authenticated user to reference a message from another private or DM channel and disclose thread context across channels. This issue is fixed in version 0.10.0.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; open-webui&lt;/p&gt;
&lt;p&gt;Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. Prior to 0.10.0, channel thread parent and reply handling did not bind parent_id to the channel in the URL, allowing an authenticated user to reference a message from another private or DM channel and disclose thread context across channels. This issue is fixed in version 0.10.0.&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://db.gcve.eu/vuln/cve-2026-59215</guid>
    </item>
    <item>
      <title>PYSEC-2026-3591 — Open WebUI: Private channel messages can be disclosed through cross-channel thread parent_id binding</title>
      <link>https://db.gcve.eu/vuln/pysec-2026-3591</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; PyPI: open-webui&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;A normal authenticated user can read the content of a message in a private channel they do not belong to. `GET /api/v1/channels/{id}/messages/{message_id}/thread` authorizes the caller against the URL channel, but the underlying thread lookup loads the thread *parent* by id and returns it without verifying the parent belongs to that channel. By requesting a thread in a channel they can access while supplying a victim channel&amp;#39;s message id as the thread root, the attacker receives the victim message — content, channel id, and author.&lt;/p&gt;
&lt;p&gt;## Affected component&lt;/p&gt;
&lt;p&gt;- `backend/open_webui/models/messages.py` — `get_messages_by_parent_id()`
- `backend/open_webui/routers/channels.py` — `get_channel_thread_messages()` (read), `new_message_handler()` (parent/reply binding on write)&lt;/p&gt;
&lt;p&gt;## Root cause&lt;/p&gt;
&lt;p&gt;`get_messages_by_parent_id(channel_id, parent_id)` filters the thread *replies* by `channel_id`, but loads the thread *parent* by id alone and appends it without requiring `parent.channel_id == channel_id`:&lt;/p&gt;
&lt;p&gt;```python
message = await db.get(Message, parent_id)     # loaded by id only — no channel binding
if not message:
    return []
# replies are filtered by channel_id ...
if len(all_messages) &amp;lt; limit:
    all_messages.append(message)               # parent appended unconditionally
```&lt;/p&gt;
&lt;p&gt;`get_channel_thread_messages()` authorizes only the URL channel, then calls `get_messages_by_parent_id(id, message_id)` with the caller-supplied `message_id`. The reply insert path (`new_message_handle…&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; PyPI: open-webui&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;A normal authenticated user can read the content of a message in a private channel they do not belong to. `GET /api/v1/channels/{id}/messages/{message_id}/thread` authorizes the caller against the URL channel, but the underlying thread lookup loads the thread *parent* by id and returns it without verifying the parent belongs to that channel. By requesting a thread in a channel they can access while supplying a victim channel&amp;#39;s message id as the thread root, the attacker receives the victim message — content, channel id, and author.&lt;/p&gt;
&lt;p&gt;## Affected component&lt;/p&gt;
&lt;p&gt;- `backend/open_webui/models/messages.py` — `get_messages_by_parent_id()`
- `backend/open_webui/routers/channels.py` — `get_channel_thread_messages()` (read), `new_message_handler()` (parent/reply binding on write)&lt;/p&gt;
&lt;p&gt;## Root cause&lt;/p&gt;
&lt;p&gt;`get_messages_by_parent_id(channel_id, parent_id)` filters the thread *replies* by `channel_id`, but loads the thread *parent* by id alone and appends it without requiring `parent.channel_id == channel_id`:&lt;/p&gt;
&lt;p&gt;```python
message = await db.get(Message, parent_id)     # loaded by id only — no channel binding
if not message:
    return []
# replies are filtered by channel_id ...
if len(all_messages) &amp;lt; limit:
    all_messages.append(message)               # parent appended unconditionally
```&lt;/p&gt;
&lt;p&gt;`get_channel_thread_messages()` authorizes only the URL channel, then calls `get_messages_by_parent_id(id, message_id)` with the caller-supplied `message_id`. The reply insert path (`new_message_handle…&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://db.gcve.eu/vuln/pysec-2026-3591</guid>
    </item>
  </channel>
</rss>
