{"id":"CVE-2026-109286","kind":"vulnerability","aliases":["CVE-2026-109286","GHSA-vpq8-f445-hcq7"],"related":[],"title":"Any website can steal a signed-in user's session token via the community stats message handler","description":"# Any website can steal a signed-in user's session token via the community stats message handler\r\n\r\n## Summary\r\nThe sync stats modal registered a `window` message listener that processed `verify:chat` messages from any web origin without checking `event.origin`, and replied to `window.opener` with target origin `*`. The chat id from the message was inserted into an authenticated request URL without encoding. Any external website that a signed-in user visits can therefore make that user's browser fetch a chosen authenticated endpoint and hand the response, including the user's session token, back to the attacker. No attacker account and no administrator action are required.\r\n\r\n## Preconditions\r\n- Community sharing enabled (`ENABLE_COMMUNITY_SHARING`, default `True`), which is what mounts the sync stats modal and its message listener.\r\n- The victim is signed in to Open WebUI in the same browser and visits an attacker-controlled page that opens Open WebUI in a popup. Deployments with community sharing disabled are not affected.\r\n\r\n## Impact\r\nThe attacker page posts a `verify:chat` message carrying a path-traversal chat id such as `../../../auths/`. The listener passes it unencoded into `GET /api/v1/chats/stats/export/<id>`, which the browser normalises to `GET /api/v1/auths/` and sends with the victim's bearer token. The listener then posts the response back to the opener with target origin `*`, so the attacker origin receives the victim's identity and raw JWT. That token replays from any client with only an `Authorization` header, granting full API access as the victim: private chats and any authenticated action under the victim's role. The demonstrated victim held the ordinary `user` role.\r\n\r\n## Fix\r\nFixed in v0.11.4 by PR #29918. The listener now ignores any message whose `event.origin` is not one of the known community origins, replies only to that validated origin instead of `*`, and the chat id is passed through `encodeURIComponent` so it can no longer escape its URL path segment. Upgrading to 0.11.4 fully resolves the issue with no further configuration.\r\n\r\n## Root cause\r\n`src/lib/components/chat/Settings/SyncStatsModal.svelte` held a `verify:chat` message handler, and `exportSingleChatStats` in `src/lib/apis/chats/index.ts` built the request URL. The handler is mounted on every page whenever community sharing is enabled, so the listener was active even while the modal was hidden. The origin allowlist that already guarded the other community message handlers was absent here, and the chat id was concatenated into the path without encoding, so an attacker-chosen value could both be accepted from an untrusted origin and redirect the authenticated request to a different endpoint.\r\n\r\n## Proof of concept\r\nReproduced against the vulnerable and fixed code in a two-origin browser harness. From an attacker origin, opening the target and repeatedly posting `{ type: 'verify:chat', data: { id: '../../../auths/' } }` caused the target to issue `GET /api/v1/auths/` carrying the victim's bearer token and to post the response back to the attacker origin, which then received the victim's email and JWT. Against the fixed code the message is rejected on the origin check and no request is made.\r\n\r\n## Credits\r\n@zyakir13","summary":"Open WebUI's community stats modal accepts unverified window messages from any origin and forwards the chat id unencoded into an authenticated request. A malicious website a signed-in user visits can make the browser fetch an authenticated endpoint and receive the response, including the user's bearer token.","severity":"high","cvss":8.6,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"open-webui","fixed":["0.11.4"],"affected":">= 0.7.0, < 0.11.4","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["ai-tooling","cwe-346","open-webui","python","self-hosted"],"not_affected_if":["community-sharing-disabled","version-0.11.4-or-later"],"how_to_check":"- Check the installed `open-webui` version against the affected range `>= 0.7.0, < 0.11.4`.\n- Check whether `ENABLE_COMMUNITY_SHARING` is enabled (default `True`); deployments with it disabled are not affected.","fix":"- Open WebUI (pypi `open-webui`): upgrade to `0.11.4`.","status":"open","published_at":"2026-09-27T19:47:06+00:00","first_seen_at":"2026-11-09T22:53:28+00:00","triaged_at":"2026-11-09T22:59:14+00:00","updated_at":"2026-11-09T23:10:12+00:00","category":"ai-tooling","confidence":0.9,"triage":{"at":"2026-11-09T22:59:14Z","model":"claude-haiku-5-5","output":{"fix":"- Open WebUI (pypi `open-webui`): upgrade to `0.11.4`.","reach":"internet","title":"Open WebUI: any website can steal signed-in user's session token","impact":"high","summary":"Open WebUI's community stats modal accepts unverified window messages from any origin and forwards the chat id unencoded into an authenticated request. A malicious website a signed-in user visits can make the browser fetch an authenticated endpoint and receive the response, including the user's bearer token.","audience":"businesses","category":"ai-tooling","nicknames":[],"who_cares":["open-webui","self-hosted","python"],"confidence":0.9,"fix_status":"available","needs_auth":"no","worst_case":"Attacker takes over the victim's Open WebUI account and reads private chats","analyst_note":"","how_to_check":"- Check the installed `open-webui` version against the affected range `>= 0.7.0, < 0.11.4`.\n- Check whether `ENABLE_COMMUNITY_SHARING` is enabled (default `True`); deployments with it disabled are not affected.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["community-sharing-disabled","version-0.11.4-or-later"],"who_is_affected":"Deployments of Open WebUI from 0.7.0 up to but not including 0.11.4 with community sharing enabled (the default) are exposed when a signed-in user visits an attacker-controlled page. Deployments with `ENABLE_COMMUNITY_SHARING` disabled are not affected, and no attacker account is needed.","user_interaction":"yes","product_ecosystem":"","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.000848,"input_tokens":5577,"output_tokens":580,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-109286':21A,29A '-2026':20A,28A '-346':37B '/../../auths':275C,541C '/api/v1/auths':290C,548C '/api/v1/chats/stats/export':283C '0.11.4':412C '29918':367C 'absent':473C 'accept':51B,495C 'access':338C 'account':195C 'action':199C,347C 'activ':454C 'administr':198C 'affect':256C 'ai':34B 'ai-tool':33B 'allowlist':463C 'alreadi':465C 'api':337C 'attack':192C,194C,239C,259C,314C,489C,528C,563C 'attacker-chosen':488C 'attacker-control':238C 'authent':66B,83B,152C,177C,346C,503C 'author':333C 'back':189C,305C,560C 'bearer':93B,297C,553C 'browser':80B,173C,234C,286C,524C 'built':434C 'carri':266C,549C 'caus':422C,542C 'chat':61B,126C,143C,264C,271C,343C,394C,427C,477C,538C 'check':133C,585C 'chosen':176C,490C 'client':329C 'code':518C,577C 'communiti':15A,48B,109C,203C,207C,251C,382C,446C,469C 'concaten':480C 'concept':511C 'configur':420C 'control':240C 'could':492C 'credit':591C 'cve':19A,27A 'cwe':36B 'data':539C 'default':209C 'demonstr':354C 'deploy':249C 'differ':507C 'disabl':253C 'email':571C 'enabl':205C,206C,449C 'encod':156C,485C 'encodeuricompon':399C 'endpoint':84B,178C,508C 'escap':405C 'even':455C 'event.origin':134C,375C 'everi':443C 'exportsinglechatstat':431C 'extern':158C 'f445':25A 'fetch':81B,174C 'fix':361C,362C,517C,576C 'forward':59B 'full':336C 'fulli':413C 'get':282C,289C,547C 'ghsa':23A 'ghsa-vpq8-f445-hcq7':22A 'grant':335C 'guard':466C 'hand':180C 'handler':18A,112C,429C,439C,471C 'har':525C 'hcq7':26A 'header':334C 'held':356C,424C 'hidden':460C 'host':44B 'id':62B,144C,272C,395C,478C,540C 'ident':320C 'ignor':371C 'impact':257C 'includ':89B,183C 'insert':149C 'instead':390C 'issu':416C,546C 'jwt':323C,573C 'known':381C 'listen':122C,222C,277C,300C,369C,452C 'longer':404C 'made':590C 'make':78B,169C 'malici':69B 'messag':17A,54B,111C,121C,127C,147C,221C,265C,373C,428C,470C,579C 'modal':50B,117C,218C,458C 'mount':214C,441C 'normalis':287C 'one':378C 'open':31A,39B,45B,229C,243C,244C,308C,530C 'open-webui':30A,38B 'ordinari':358C 'origin':57B,131C,141C,311C,315C,383C,389C,462C,499C,523C,529C,564C,584C 'page':241C,260C,444C 'pass':278C,397C 'path':269C,408C,483C 'path-travers':268C 'popup':248C 'post':261C,302C,535C,557C 'pr':366C 'precondit':202C 'privat':342C 'process':124C 'proof':509C 'python':41B 'raw':322C 'receiv':86B,316C,567C 'redirect':501C 'regist':118C 'reject':581C 'repeat':534C 'replay':326C 'repli':136C,384C 'reproduc':512C 'request':67B,153C,436C,504C,588C 'requir':201C 'resolv':414C 'respons':88B,182C,304C,559C 'role':352C,360C 'root':421C 'segment':409C 'self':43B 'self-host':42B 'send':292C 'session':11A,105C,187C 'share':204C,208C,252C,447C 'sign':7A,73B,101C,163C,226C 'signed-in':6A,72B,100C,162C 'src/lib/apis/chats/index.ts':433C 'src/lib/components/chat/settings/syncstatsmodal.svelte':423C 'stat':16A,49B,110C,116C,217C 'steal':4A,98C 'summari':113C 'sync':115C,216C 'target':140C,310C,532C,544C 'therefor':168C 'token':12A,94B,106C,188C,298C,325C,554C 'tool':35B 'travers':270C 'true':210C 'two':522C 'two-origin':521C 'type':536C 'unencod':63B,280C 'untrust':498C 'unverifi':52B 'upgrad':410C 'url':154C,407C,437C 'user':9A,75B,91B,103C,165C,171C,185C,359C 'v0.11.4':364C 'valid':388C 'valu':491C 'verifi':125C,263C,426C,537C 'via':13A,107C 'victim':224C,295C,318C,341C,350C,355C,551C,569C 'visit':76B,166C,236C 'vpq8':24A 'vulner':515C 'web':130C 'websit':2A,70B,96C,159C 'webui':32A,40B,46B,230C,245C 'whenev':445C 'whose':374C 'window':53B,120C 'window.opener':138C 'without':132C,155C,484C 'zyakir13':592C","nicknames":[],"mitigations":[],"who_affected":"Deployments of Open WebUI from 0.7.0 up to but not including 0.11.4 with community sharing enabled (the default) are exposed when a signed-in user visits an attacker-controlled page. Deployments with `ENABLE_COMMUNITY_SHARING` disabled are not affected, and no attacker account is needed.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":["openwebui"],"ptokens":["open","webui"],"labels":["aitooling","cwe346","high","openwebui","pypi","python","selfhosted"],"campaign_type":null,"search_a":"'-109286':21A,29A '-2026':20A,28A 'communiti':15A 'cve':19A,27A 'f445':25A 'ghsa':23A 'ghsa-vpq8-f445-hcq7':22A 'handler':18A 'hcq7':26A 'messag':17A 'open':31A 'open-webui':30A 'session':11A 'sign':7A 'signed-in':6A 'stat':16A 'steal':4A 'token':12A 'user':9A 'via':13A 'vpq8':24A 'websit':2A 'webui':32A","search_b":"'-346':37B 'accept':51B 'ai':34B 'ai-tool':33B 'authent':66B,83B 'bearer':93B 'browser':80B 'chat':61B 'communiti':48B 'cwe':36B 'endpoint':84B 'fetch':81B 'forward':59B 'host':44B 'id':62B 'includ':89B 'make':78B 'malici':69B 'messag':54B 'modal':50B 'open':39B,45B 'open-webui':38B 'origin':57B 'python':41B 'receiv':86B 'request':67B 'respons':88B 'self':43B 'self-host':42B 'sign':73B 'signed-in':72B 'stat':49B 'token':94B 'tool':35B 'unencod':63B 'unverifi':52B 'user':75B,91B 'visit':76B 'websit':70B 'webui':40B,46B 'window':53B","search_c":"'/../../auths':275C,541C '/api/v1/auths':290C,548C '/api/v1/chats/stats/export':283C '0.11.4':412C '29918':367C 'absent':473C 'accept':495C 'access':338C 'account':195C 'action':199C,347C 'activ':454C 'administr':198C 'affect':256C 'allowlist':463C 'alreadi':465C 'api':337C 'attack':192C,194C,239C,259C,314C,489C,528C,563C 'attacker-chosen':488C 'attacker-control':238C 'authent':152C,177C,346C,503C 'author':333C 'back':189C,305C,560C 'bearer':297C,553C 'browser':173C,234C,286C,524C 'built':434C 'carri':266C,549C 'caus':422C,542C 'chat':126C,143C,264C,271C,343C,394C,427C,477C,538C 'check':133C,585C 'chosen':176C,490C 'client':329C 'code':518C,577C 'communiti':109C,203C,207C,251C,382C,446C,469C 'concaten':480C 'concept':511C 'configur':420C 'control':240C 'could':492C 'credit':591C 'data':539C 'default':209C 'demonstr':354C 'deploy':249C 'differ':507C 'disabl':253C 'email':571C 'enabl':205C,206C,449C 'encod':156C,485C 'encodeuricompon':399C 'endpoint':178C,508C 'escap':405C 'even':455C 'event.origin':134C,375C 'everi':443C 'exportsinglechatstat':431C 'extern':158C 'fetch':174C 'fix':361C,362C,517C,576C 'full':336C 'fulli':413C 'get':282C,289C,547C 'grant':335C 'guard':466C 'hand':180C 'handler':112C,429C,439C,471C 'har':525C 'header':334C 'held':356C,424C 'hidden':460C 'id':144C,272C,395C,478C,540C 'ident':320C 'ignor':371C 'impact':257C 'includ':183C 'insert':149C 'instead':390C 'issu':416C,546C 'jwt':323C,573C 'known':381C 'listen':122C,222C,277C,300C,369C,452C 'longer':404C 'made':590C 'make':169C 'messag':111C,121C,127C,147C,221C,265C,373C,428C,470C,579C 'modal':117C,218C,458C 'mount':214C,441C 'normalis':287C 'one':378C 'open':229C,243C,244C,308C,530C 'ordinari':358C 'origin':131C,141C,311C,315C,383C,389C,462C,499C,523C,529C,564C,584C 'page':241C,260C,444C 'pass':278C,397C 'path':269C,408C,483C 'path-travers':268C 'popup':248C 'post':261C,302C,535C,557C 'pr':366C 'precondit':202C 'privat':342C 'process':124C 'proof':509C 'raw':322C 'receiv':316C,567C 'redirect':501C 'regist':118C 'reject':581C 'repeat':534C 'replay':326C 'repli':136C,384C 'reproduc':512C 'request':153C,436C,504C,588C 'requir':201C 'resolv':414C 'respons':182C,304C,559C 'role':352C,360C 'root':421C 'segment':409C 'send':292C 'session':105C,187C 'share':204C,208C,252C,447C 'sign':101C,163C,226C 'signed-in':100C,162C 'src/lib/apis/chats/index.ts':433C 'src/lib/components/chat/settings/syncstatsmodal.svelte':423C 'stat':110C,116C,217C 'steal':98C 'summari':113C 'sync':115C,216C 'target':140C,310C,532C,544C 'therefor':168C 'token':106C,188C,298C,325C,554C 'travers':270C 'true':210C 'two':522C 'two-origin':521C 'type':536C 'unencod':280C 'untrust':498C 'upgrad':410C 'url':154C,407C,437C 'user':103C,165C,171C,185C,359C 'v0.11.4':364C 'valid':388C 'valu':491C 'verifi':125C,263C,426C,537C 'via':107C 'victim':224C,295C,318C,341C,350C,355C,551C,569C 'visit':166C,236C 'vulner':515C 'web':130C 'websit':96C,159C 'webui':230C,245C 'whenev':445C 'whose':374C 'window':120C 'window.opener':138C 'without':132C,155C,484C 'zyakir13':592C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-09-27T19:47:06+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"disclosure@vulncheck.com","poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-vpq8-f445-hcq7","url":"https://github.com/open-webui/open-webui/security/advisories/GHSA-vpq8-f445-hcq7","severity":"high","published_at":"2026-09-27T19:47:06+00:00","modified_at":"2026-10-28T20:46:55+00:00","first_seen_at":"2026-11-09T22:53:28+00:00","fetched_at":"2026-11-09T22:53:28+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-109286","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-109286","severity":null,"published_at":"2026-10-12T17:17:21+00:00","modified_at":"2026-10-18T12:17:04+00:00","first_seen_at":"2026-11-09T23:10:12+00:00","fetched_at":"2026-11-09T23:10:12+00:00","note":null}],"documents":[{"id":110656,"url":"https://github.com/open-webui/open-webui/security/advisories/GHSA-vpq8-f445-hcq7","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":"2026-09-27T19:47:06+00:00","relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":111020,"url":"https://www.vulncheck.com/advisories/open-webui-0.7.0-before-0.11.4-session-token-theft-via-syncstatsmodal","title":"Third-party advisory: www.vulncheck.com","kind":"advisory","source":"nvd","publisher":"research","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Third-party advisory: www.vulncheck.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}