{"id":"CVE-2026-109293","kind":"vulnerability","aliases":["CVE-2026-109293","GHSA-2h26-836q-4jh2"],"related":[],"title":"Tool source code disclosed to read-only users via the tool export endpoint","description":"# Tool source code disclosed to read-only users via the tool export endpoint\r\n\r\n## Summary\r\nA user allowed to export tools received the full Python source of every tool that had merely been shared with them for reading. Since 0.11.0 tool source is writer-only: a read-only recipient can use a shared tool, and the tool's detail view withholds its source from them. The bulk export returned it anyway, because it selected every tool the caller could read.\r\n\r\n## Preconditions\r\n- Authentication enabled (`WEBUI_AUTH=true`, default) and plugins enabled (`ENABLE_PLUGINS=true`, default).\r\n- The attacker is an authenticated non-admin who holds the tool export permission (`workspace.tools_export`, off by default, set with `USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT` or granted by an admin in default or group permissions).\r\n- A tool owned by someone else is shared with a read grant to the attacker, to one of their groups, or to all users.\r\n\r\nDeployments that never grant the tool export permission to non-admins, or that share tools only with users who already hold write access, are not affected.\r\n\r\n## Impact\r\nA non-admin with export rights obtains the server-side source of every tool shared with them read-only, in one request. Tool source commonly embeds API keys, credentials and internal service URLs, so the loss often reaches beyond the code itself. Confidentiality only: the export grants no ability to modify or run tools, and has no integrity or availability impact.\r\n\r\n## Fix\r\nFixed in 0.11.4 by #29310. The export now returns only tools the caller owns or holds write access to, the same scope the per-tool export and the model export already used. Upgrading fully resolves the issue with no configuration change.\r\n\r\n## Root cause\r\nAffected component: `GET /api/v1/tools/export` in `backend/open_webui/routers/tools.py`. Affected setup: releases 0.11.0 through 0.11.3. Tool export has been open to non-admins since 0.6.37, but before 0.11.0 a read-only recipient could already read a shared tool's source in its detail view, so the export disclosed nothing beyond that.\r\n\r\nThe export response deliberately includes each tool's source, since exporting is how a writer takes a copy of their tools. The handler, however, built its list with the default read scope of the tool query, so every tool shared read-only with the caller was exported with its source. When 0.11.0 made source writer-only on the detail endpoint, the export path was left on the read scope and kept returning it.\r\n\r\n## Proof of concept\r\nAgainst a fresh instance, with an admin and a second account `bob` of role `user`:\r\n\r\n1. As the admin, enable tool export for users (`POST /api/v1/users/default/permissions` with `workspace.tools_export: true`).\r\n2. As the admin, create a tool whose source contains a marker and share it read-only with bob:\r\n\r\n```\r\nPOST /api/v1/tools/create\r\n{\"id\": \"readtool\", \"name\": \"Read Tool\",\r\n \"content\": \"API_KEY = \\\"TOOL_SRC_SECRET\\\"\\nclass Tools:\\n    def hello(self) -> str:\\n        return 'hi'\\n\",\r\n \"meta\": {\"description\": \"poc\"},\r\n \"access_grants\": [{\"principal_type\": \"user\", \"principal_id\": \"<bob id>\", \"permission\": \"read\"}]}\r\n```\r\n\r\n3. As bob:\r\n\r\n```\r\nGET /api/v1/tools/id/readtool  -> 200, no content field\r\nGET /api/v1/tools/export       -> 200, [{\"id\": \"readtool\", \"content\": \"API_KEY = \\\"TOOL_SRC_SECRET\\\" ...\", ...}]\r\n```\r\n\r\nOn 0.11.4 the same export returns only tools bob owns or can write, and `readtool` is absent, while the admin still exports it.\r\n\r\n## Credits\r\n- gigioneggiando: reported the source disclosure through the tool export endpoint.","summary":"Open WebUI's tool export endpoint returned the full Python source of every tool shared read-only with a non-admin user, including any embedded API keys or credentials. An authenticated non-admin with tool export permission can read that source, but cannot modify or run the tools.","severity":"high","cvss":7.1,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"open-webui","fixed":["0.11.4"],"affected":">= 0.11.0, < 0.11.4","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["ai-tooling","cwe-200","open-webui","python","self-hosted"],"not_affected_if":["managed-hosting","no-read-only-tool-shares","tools-export-admin-only"],"how_to_check":"- Check the installed version with `pip show open-webui` and confirm whether it is between `0.11.0` and `0.11.3`.\n- Check whether non-admin users hold the `workspace.tools_export` permission, set by `USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT` or in default or group permissions.\n- Check whether any tools owned by one user are shared read-only with other users, groups or all users.","fix":"- `open-webui` `0.11.4` (fixed version per the product data)","status":"open","published_at":"2026-09-27T15:58:57+00:00","first_seen_at":"2026-11-09T22:53:26+00:00","triaged_at":"2026-11-09T23:00:47+00:00","updated_at":"2026-11-09T23:10:12+00:00","category":"ai-tooling","confidence":0.9,"triage":{"at":"2026-11-09T23:00:47Z","model":"claude-haiku-5-5","output":{"fix":"- `open-webui` `0.11.4` (fixed version per the product data)","reach":"network","title":"Open WebUI: tool export leaks source code of read-only shared tools","impact":"medium","summary":"Open WebUI's tool export endpoint returned the full Python source of every tool shared read-only with a non-admin user, including any embedded API keys or credentials. An authenticated non-admin with tool export permission can read that source, but cannot modify or run the tools.","audience":"businesses","category":"ai-tooling","nicknames":[],"who_cares":["open-webui","self-hosted","python"],"confidence":0.9,"fix_status":"available","needs_auth":"yes","worst_case":"Non-admin reads server-side source of shared tools, including embedded credentials.","analyst_note":"","how_to_check":"- Check the installed version with `pip show open-webui` and confirm whether it is between `0.11.0` and `0.11.3`.\n- Check whether non-admin users hold the `workspace.tools_export` permission, set by `USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT` or in default or group permissions.\n- Check whether any tools owned by one user are shared read-only with other users, groups or all users.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["tools-export-admin-only","no-read-only-tool-shares","managed-hosting"],"who_is_affected":"Only self-hosted Open WebUI deployments on 0.11.0 through 0.11.3 where non-admin users have tool export rights and some tools are shared read-only with them. Deployments that never grant tool export to non-admins, or that share tools only with users who already have write access, are not affected. Upgrading to 0.11.4 resolves it with no configuration change.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000901,"input_tokens":5784,"output_tokens":645,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-109293':17A,25A '-200':33B '-2026':16A,24A '/api/v1/tools/create':564C '/api/v1/tools/export':388C,609C '/api/v1/tools/id/readtool':603C '/api/v1/users/default/permissions':538C '0.11.0':131C,394C,410C,487C '0.11.3':396C '0.11.4':343C,620C '0.6.37':407C '1':528C '2':543C '200':604C,610C '29310':345C '2h26':20A '3':599C '4jh2':22A '836q':21A 'abil':327C 'absent':635C 'access':271C,358C,590C 'account':523C 'admin':63B,76B,195C,218C,259C,279C,405C,519C,531C,546C,638C 'affect':274C,385C,391C 'ai':30B 'ai-tool':29B 'allow':109C 'alreadi':268C,372C,417C 'anyway':164C 'api':68B,305C,571C,614C 'attack':189C,238C 'auth':178C 'authent':73B,175C,192C 'avail':338C 'backend/open_webui/routers/tools.py':390C 'beyond':317C,433C 'bob':524C,562C,601C,627C 'built':459C 'bulk':160C 'caller':171C,353C,480C 'cannot':86B 'caus':384C 'chang':382C 'code':3A,94C,319C 'common':303C 'compon':386C 'concept':512C 'confidenti':321C 'configur':381C 'contain':552C 'content':570C,606C,613C 'copi':452C 'could':172C,416C 'creat':547C 'credenti':71B,307C 'credit':642C 'cve':15A,23A 'cwe':32B 'def':579C 'default':180C,187C,206C,220C,464C 'deliber':438C 'deploy':248C 'descript':588C 'detail':152C,426C,495C 'disclos':4A,95C,431C 'disclosur':647C 'els':229C 'emb':304C 'embed':67B 'enabl':176C,183C,184C,532C 'endpoint':14A,46B,105C,496C,652C 'everi':53B,119C,168C,290C,472C 'export':13A,45B,79B,104C,111C,161C,200C,203C,213C,254C,281C,324C,347C,367C,371C,398C,430C,436C,445C,482C,498C,534C,541C,623C,640C,651C 'field':607C 'fix':340C,341C 'fresh':515C 'full':49B,115C 'fulli':375C 'get':387C,602C,608C 'ghsa':19A 'ghsa-2h26-836q-4jh2':18A 'gigioneggiando':643C 'grant':215C,235C,251C,325C,591C 'group':222C,243C 'handler':457C 'hello':580C 'hi':585C 'hold':197C,269C,356C 'host':40B 'howev':458C 'id':565C,596C,611C 'impact':275C,339C 'includ':65B,439C 'instanc':516C 'integr':336C 'intern':309C 'issu':378C 'kept':507C 'key':69B,306C,572C,615C 'left':501C 'list':461C 'loss':314C 'made':488C 'marker':554C 'mere':123C 'meta':587C 'model':370C 'modifi':87B,329C 'n':578C,583C,586C 'name':567C 'nclass':576C 'never':250C 'non':62B,75B,194C,258C,278C,404C 'non-admin':61B,74B,193C,257C,277C,403C 'noth':432C 'obtain':283C 'often':315C 'one':240C,299C 'open':27A,35B,41B,401C 'open-webui':26A,34B 'own':226C,354C,628C 'path':499C 'per':365C 'per-tool':364C 'permiss':80B,201C,210C,223C,255C,597C 'plugin':182C,185C 'poc':589C 'post':537C,563C 'precondit':174C 'princip':592C,595C 'proof':510C 'python':37B,50B,116C 'queri':470C 'reach':316C 'read':7A,57B,82B,98C,129C,140C,173C,234C,296C,413C,418C,465C,476C,504C,559C,568C,598C 'read-on':6A,56B,97C,139C,295C,412C,475C,558C 'readtool':566C,612C,633C 'receiv':113C 'recipi':142C,415C 'releas':393C 'report':644C 'request':300C 'resolv':376C 'respons':437C 'return':47B,162C,349C,508C,584C,624C 'right':282C 'role':526C 'root':383C 'run':89B,331C 'scope':362C,466C,505C 'second':522C 'secret':575C,618C 'select':167C 'self':39B,581C 'self-host':38B 'server':286C 'server-sid':285C 'servic':310C 'set':207C 'setup':392C 'share':55B,125C,146C,231C,262C,292C,420C,474C,556C 'side':287C 'sinc':130C,406C,444C 'someon':228C 'sourc':2A,51B,84B,93C,117C,133C,156C,288C,302C,423C,443C,485C,489C,551C,646C 'src':574C,617C 'still':639C 'str':582C 'summari':106C 'take':450C 'tool':1A,12A,31B,44B,54B,78B,91B,92C,103C,112C,120C,132C,147C,150C,169C,199C,212C,225C,253C,263C,291C,301C,332C,351C,366C,397C,421C,441C,455C,469C,473C,533C,549C,569C,573C,577C,616C,626C,650C 'true':179C,186C,542C 'type':593C 'upgrad':374C 'url':311C 'use':144C,373C 'user':9A,64B,100C,108C,209C,247C,266C,527C,536C,594C 'via':10A,101C 'view':153C,427C 'webui':28A,36B,42B,177C 'whose':550C 'withhold':154C 'workspac':211C 'workspace.tools':202C,540C 'write':270C,357C,631C 'writer':136C,449C,491C 'writer-on':135C,490C","nicknames":[],"mitigations":[],"who_affected":"Only self-hosted Open WebUI deployments on 0.11.0 through 0.11.3 where non-admin users have tool export rights and some tools are shared read-only with them. Deployments that never grant tool export to non-admins, or that share tools only with users who already have write access, are not affected. Upgrading to 0.11.4 resolves it with no configuration change.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":["openwebui"],"ptokens":["open","webui"],"labels":["aitooling","cwe200","high","openwebui","pypi","python","selfhosted"],"campaign_type":null,"search_a":"'-109293':17A,25A '-2026':16A,24A '2h26':20A '4jh2':22A '836q':21A 'code':3A 'cve':15A,23A 'disclos':4A 'endpoint':14A 'export':13A 'ghsa':19A 'ghsa-2h26-836q-4jh2':18A 'open':27A 'open-webui':26A 'read':7A 'read-on':6A 'sourc':2A 'tool':1A,12A 'user':9A 'via':10A 'webui':28A","search_b":"'-200':33B 'admin':63B,76B 'ai':30B 'ai-tool':29B 'api':68B 'authent':73B 'cannot':86B 'credenti':71B 'cwe':32B 'embed':67B 'endpoint':46B 'everi':53B 'export':45B,79B 'full':49B 'host':40B 'includ':65B 'key':69B 'modifi':87B 'non':62B,75B 'non-admin':61B,74B 'open':35B,41B 'open-webui':34B 'permiss':80B 'python':37B,50B 'read':57B,82B 'read-on':56B 'return':47B 'run':89B 'self':39B 'self-host':38B 'share':55B 'sourc':51B,84B 'tool':31B,44B,54B,78B,91B 'user':64B 'webui':36B,42B","search_c":"'/api/v1/tools/create':564C '/api/v1/tools/export':388C,609C '/api/v1/tools/id/readtool':603C '/api/v1/users/default/permissions':538C '0.11.0':131C,394C,410C,487C '0.11.3':396C '0.11.4':343C,620C '0.6.37':407C '1':528C '2':543C '200':604C,610C '29310':345C '3':599C 'abil':327C 'absent':635C 'access':271C,358C,590C 'account':523C 'admin':195C,218C,259C,279C,405C,519C,531C,546C,638C 'affect':274C,385C,391C 'allow':109C 'alreadi':268C,372C,417C 'anyway':164C 'api':305C,571C,614C 'attack':189C,238C 'auth':178C 'authent':175C,192C 'avail':338C 'backend/open_webui/routers/tools.py':390C 'beyond':317C,433C 'bob':524C,562C,601C,627C 'built':459C 'bulk':160C 'caller':171C,353C,480C 'caus':384C 'chang':382C 'code':94C,319C 'common':303C 'compon':386C 'concept':512C 'confidenti':321C 'configur':381C 'contain':552C 'content':570C,606C,613C 'copi':452C 'could':172C,416C 'creat':547C 'credenti':307C 'credit':642C 'def':579C 'default':180C,187C,206C,220C,464C 'deliber':438C 'deploy':248C 'descript':588C 'detail':152C,426C,495C 'disclos':95C,431C 'disclosur':647C 'els':229C 'emb':304C 'enabl':176C,183C,184C,532C 'endpoint':105C,496C,652C 'everi':119C,168C,290C,472C 'export':104C,111C,161C,200C,203C,213C,254C,281C,324C,347C,367C,371C,398C,430C,436C,445C,482C,498C,534C,541C,623C,640C,651C 'field':607C 'fix':340C,341C 'fresh':515C 'full':115C 'fulli':375C 'get':387C,602C,608C 'gigioneggiando':643C 'grant':215C,235C,251C,325C,591C 'group':222C,243C 'handler':457C 'hello':580C 'hi':585C 'hold':197C,269C,356C 'howev':458C 'id':565C,596C,611C 'impact':275C,339C 'includ':439C 'instanc':516C 'integr':336C 'intern':309C 'issu':378C 'kept':507C 'key':306C,572C,615C 'left':501C 'list':461C 'loss':314C 'made':488C 'marker':554C 'mere':123C 'meta':587C 'model':370C 'modifi':329C 'n':578C,583C,586C 'name':567C 'nclass':576C 'never':250C 'non':194C,258C,278C,404C 'non-admin':193C,257C,277C,403C 'noth':432C 'obtain':283C 'often':315C 'one':240C,299C 'open':401C 'own':226C,354C,628C 'path':499C 'per':365C 'per-tool':364C 'permiss':201C,210C,223C,255C,597C 'plugin':182C,185C 'poc':589C 'post':537C,563C 'precondit':174C 'princip':592C,595C 'proof':510C 'python':116C 'queri':470C 'reach':316C 'read':98C,129C,140C,173C,234C,296C,413C,418C,465C,476C,504C,559C,568C,598C 'read-on':97C,139C,295C,412C,475C,558C 'readtool':566C,612C,633C 'receiv':113C 'recipi':142C,415C 'releas':393C 'report':644C 'request':300C 'resolv':376C 'respons':437C 'return':162C,349C,508C,584C,624C 'right':282C 'role':526C 'root':383C 'run':331C 'scope':362C,466C,505C 'second':522C 'secret':575C,618C 'select':167C 'self':581C 'server':286C 'server-sid':285C 'servic':310C 'set':207C 'setup':392C 'share':125C,146C,231C,262C,292C,420C,474C,556C 'side':287C 'sinc':130C,406C,444C 'someon':228C 'sourc':93C,117C,133C,156C,288C,302C,423C,443C,485C,489C,551C,646C 'src':574C,617C 'still':639C 'str':582C 'summari':106C 'take':450C 'tool':92C,103C,112C,120C,132C,147C,150C,169C,199C,212C,225C,253C,263C,291C,301C,332C,351C,366C,397C,421C,441C,455C,469C,473C,533C,549C,569C,573C,577C,616C,626C,650C 'true':179C,186C,542C 'type':593C 'upgrad':374C 'url':311C 'use':144C,373C 'user':100C,108C,209C,247C,266C,527C,536C,594C 'via':101C 'view':153C,427C 'webui':177C 'whose':550C 'withhold':154C 'workspac':211C 'workspace.tools':202C,540C 'write':270C,357C,631C 'writer':136C,449C,491C 'writer-on':135C,490C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-09-27T15:58:57+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/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-2h26-836q-4jh2","url":"https://github.com/open-webui/open-webui/security/advisories/GHSA-2h26-836q-4jh2","severity":"medium","published_at":"2026-09-27T15:58:57+00:00","modified_at":"2026-10-28T20:57:20+00:00","first_seen_at":"2026-11-09T22:53:26+00:00","fetched_at":"2026-11-09T22:53:26+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-109293","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-109293","severity":null,"published_at":"2026-10-12T17:17:22+00:00","modified_at":"2026-10-13T20:39:48+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":110643,"url":"https://github.com/open-webui/open-webui/security/advisories/GHSA-2h26-836q-4jh2","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":"2026-09-27T15:58:57+00:00","relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":111049,"url":"https://www.vulncheck.com/advisories/open-webui-0.11.0-before-0.11.4-tool-source-disclosure-via-tool-export-endpoint","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"}