Skip to main content

Open WebUI CVE-2026-54008

| EUVDEUVD-2026-38534 HIGH
Server-Side Request Forgery (SSRF) (CWE-918)
2026-06-17 https://github.com/open-webui/open-webui GHSA-226f-f24g-524w
8.5
CVSS 3.1 · Vendor: https://github.com/open-webui/open-webui
Share

Severity by source

Vendor (https://github.com/open-webui/open-webui) PRIMARY
8.5 HIGH
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
vuln.today AI
8.5 HIGH

Network reachable OAuth login flow, no UI, requires any IdP identity (PR:L); SSRF reaches systems beyond auth boundary (S:C); high read of internal data (C:H), limited integrity from stored profile field (I:L).

3.1 AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
4.0 AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:N/SC:H/SI:N/SA:N

Primary rating from Vendor (https://github.com/open-webui/open-webui).

CVSS VectorVendor: https://github.com/open-webui/open-webui

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
Low
Availability
None

Lifecycle Timeline

3
Source Code Evidence Fetched
Jun 18, 2026 - 01:30 vuln.today
Analysis Generated
Jun 18, 2026 - 01:30 vuln.today
CVE Published
Jun 17, 2026 - 14:10 github-advisory
HIGH 8.5

DescriptionCVE.org

Summary

backend/open_webui/utils/oauth.py::_process_picture_url (v0.9.5, lines 1435-1470) calls validate_url(picture_url) on the initial URL only, then invokes aiohttp.ClientSession.get(picture_url, ...) without allow_redirects=False. aiohttp's default is allow_redirects=True, max_redirects=10; the function does not pass the project's AIOHTTP_CLIENT_ALLOW_REDIRECTS env constant either. An attacker with a valid OAuth IdP identity can therefore submit a public URL that 302-redirects to an internal address and read the internal response body via the attacker's own profile_image_url field.

This is the same redirect-bypass class as CVE-2026-45401 (GHSA-rh5x-h6pp-cjj6), on a 6th call site that the v0.9.5 patch missed. CVE-2026-45401's advisory body enumerates exactly five affected paths — SafeWebBaseLoader._scrape, _fetch, get_content_from_url, load_url_image, get_image_base64_from_url — none in utils/oauth.py.

Vulnerable code (v0.9.5)

backend/open_webui/utils/oauth.py, lines 1435-1470:

python
async def _process_picture_url(self, picture_url: str, access_token: str = None) -> str:
    if not picture_url:
        return '/user.png'
    try:
        validate_url(picture_url)
# initial URL only

        get_kwargs = {}
        if access_token:
            get_kwargs['headers'] = {'Authorization': f'Bearer {access_token}'}
        async with aiohttp.ClientSession(trust_env=True) as session:
            async with session.get(picture_url, **get_kwargs,
                                   ssl=AIOHTTP_CLIENT_SESSION_SSL) as resp:
#                       ^^^^^^^^^^^ no allow_redirects=False
                if resp.ok:
                    picture = await resp.read()
                    base64_encoded_picture = base64.b64encode(picture).decode('utf-8')
                    guessed_mime_type = mimetypes.guess_type(picture_url)[0]
                    if guessed_mime_type is None:
                        guessed_mime_type = 'image/jpeg'
                    return f'data:{guessed_mime_type};base64,{base64_encoded_picture}'
                ...

The function is invoked at oauth.py:1556 (new-user OAuth signup) and oauth.py:1536 (existing-user picture update on login). Neither call site re-validates after redirect-following.

backend/open_webui/retrieval/web/utils.py (v0.9.5) imports the env constant AIOHTTP_CLIENT_ALLOW_REDIRECTS at line 51 and uses it on the five paths patched by CVE-2026-45401. utils/oauth.py does not import or reference it.

Exploitation

Preconditions:

  • ENABLE_OAUTH_SIGNUP=true or OAUTH_UPDATE_PICTURE_ON_LOGIN=true (common in production OAuth-IdP deployments)
  • Attacker has a valid identity on the configured OAuth IdP (Google, Microsoft, GitHub, or any generic OIDC provider)

Steps:

  1. Attacker hosts a redirect endpoint at http://attacker.example/r on a public IP. validate_url("http://attacker.example/r") returns True (is_global=True for public IPs).
  2. Attacker sets their IdP picture claim to http://attacker.example/r.
  3. Attacker signs in to open-webui via OAuth. open-webui invokes _process_picture_url("http://attacker.example/r", ...).
  4. validate_url accepts the public URL. session.get("http://attacker.example/r") is invoked.
  5. attacker.example responds HTTP/1.1 302 Found\r\nLocation: http://127.0.0.1:11434/api/tags. (Or http://169.254.169.254/latest/meta-data/iam/security-credentials/, RFC1918 internal services, etc.)
  6. aiohttp follows the redirect server-side. No re-validation.
  7. The internal response body is read into picture, base64-encoded, and stored as profile_image_url = "data:image/jpeg;base64,..." on the attacker's account.
  8. Attacker reads back via GET /api/v1/auths/. Decode the base64 payload to get the full internal response body.

Impact

Full-read SSRF, identical read-back primitive to CVE-2026-45338:

  • Cloud metadata services (AWS IMDSv1 at 169.254.169.254, GCP metadata.google.internal, Azure IMDS) → IAM credentials, managed-identity tokens
  • Localhost-bound services (Ollama at :11434, Redis, Elasticsearch, internal Postgres exporters)
  • RFC1918 internal infrastructure not exposed to the internet

Distinction from prior CVEs

Prior CVEThis findingDistinguishing fact
CVE-2026-45338 (GHSA-24c9)_process_picture_url had no validate_url() call at allFixed in v0.9.0 by adding the call. Ours is the call being insufficient because it doesn't loop over redirect targets. Different mechanism, different fix.
CVE-2026-45400 (GHSA-8w7q)validate_url() had urlparse-vs-requests parser disagreement on \@ charsFixed in v0.9.5 by char-blocklist. Ours is post-validation redirect-following — orthogonal mechanism.
CVE-2026-45401 (GHSA-rh5x)Five paths in retrieval, routers/images, utils/files, utils/middlewareParent class. Same CWE-918 redirect-bypass mechanism. utils/oauth.py::_process_picture_url is not among the five paths in the parent advisory's "Affected code paths" section. Same class, missed sink. Direct sibling.

Suggested fix

python
async with session.get(
    picture_url,
    **get_kwargs,
    ssl=AIOHTTP_CLIENT_SESSION_SSL,
    allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS,
# add
) as resp:

Or, if redirects must remain enabled by default, wrap in a manual-follow loop that re-invokes validate_url() on each Location header. This mirrors the fix shape applied to the five paths in CVE-2026-45401.

Affected versions

Vulnerable: <= 0.9.5 Fix: 0.9.6

References

  • CVE-2026-45401 / GHSA-rh5x-h6pp-cjj6 (parent cluster, redirect-bypass on 5 paths)
  • CVE-2026-45338 / GHSA-24c9-2m8q-qhmh (original _process_picture_url SSRF, patched v0.9.0)
  • CVE-2026-45400 / GHSA-8w7q-q5jp-jvgx (validate_url parser-disagreement bypass, patched v0.9.5)
  • open-webui issue #24560 (corroborates that the v0.9.5 redirect-fix was applied piecemeal across call sites)

Proof of Concept

End-to-end PoC executed against ghcr.io/open-webui/open-webui:v0.9.5 in Docker compose. Three services: attacker (OIDC IdP + 302-redirect endpoint on evil.example.com:9001/redirect), canary (internal target on internal-target.local:9002/sentinel), open-webui v0.9.5.

Fresh-CSPRNG sentinel generated after OAuth state-establishing call (per Gate 5.5 oracle protocol): SSRF-POC-5580111b2a0d7d0c8324bfa92a0d9d09.

Result:

  • profile_image_url field after OAuth login: data:image/jpeg;base64,U1NSRi1QT0MtNTU4MDExMWIyYTBkN2QwYzgzMjRiZmE5MmEwZDlkMDk=
  • Base64 decode: SSRF-POC-5580111b2a0d7d0c8324bfa92a0d9d09 (byte-for-byte sentinel match)
  • Canary log: !!! SSRF HIT - sentinel served

Chain confirmed: OAuth login → IdP returns picture claim evil.example.com:9001/redirect → validate_url() accepts FQDN → aiohttp.ClientSession.get(...) follows 302 to internal-target.local:9002/sentinel server-side without re-validation → response body base64-encoded into attacker's profile_image_url → readable via GET /api/v1/auths/.

PoC artifacts (compose, attacker server, canary, run/verify scripts, full transcript) available on request.

Reporter

Matteo Panzeri — GitHub: matte1782, contact: matteo1782@gmail.com. Requesting CVE credit as Matteo Panzeri.

AnalysisAI

Server-side request forgery in Open WebUI versions 0.9.5 and earlier allows authenticated OAuth users to read arbitrary internal HTTP responses by abusing the _process_picture_url function in backend/open_webui/utils/oauth.py, which validates only the initial URL and then permits aiohttp's default 10-redirect follow chain to reach internal addresses. The decoded response body is stored in the attacker's profile_image_url and retrievable via GET /api/v1/auths/, yielding cloud metadata credentials and access to localhost-bound services. Publicly available exploit code exists (detailed sentinel-verified PoC supplied by the reporter); no public exploit identified at time of analysis in the form of weaponized tooling, and the CVE is not on the CISA KEV list.

Technical ContextAI

The root cause is CWE-918 Server-Side Request Forgery manifesting as an incomplete-fix sibling of CVE-2026-45401. Open WebUI uses Python's aiohttp library, whose ClientSession.get() defaults to allow_redirects=True with max_redirects=10. The project introduced an AIOHTTP_CLIENT_ALLOW_REDIRECTS env constant and applied it to five fetch sinks in retrieval/web/utils.py, but the OAuth profile-picture sink at utils/oauth.py:1435-1470 was missed: it calls validate_url() on the initial URL only, then issues session.get(picture_url, ssl=AIOHTTP_CLIENT_SESSION_SSL) with no allow_redirects=False and no per-hop revalidation. Because validate_url treats public hosts as safe (is_global=True), an attacker-controlled HTTP 302 to an RFC1918 address, 127.0.0.1, or cloud-metadata endpoints such as 169.254.169.254 is followed server-side. CPE pkg:pip/open-webui confirms the affected distribution is the Python package shipped via PyPI and the ghcr.io/open-webui/open-webui container image.

RemediationAI

Vendor-released patch: upgrade open-webui to version 0.9.6 or later (pip/PyPI and the corresponding ghcr.io/open-webui/open-webui image tag), per advisory GHSA-226f-f24g-524w at https://github.com/open-webui/open-webui/security/advisories/GHSA-226f-f24g-524w. If immediate upgrade is not possible, set ENABLE_OAUTH_SIGNUP=false to block attacker self-onboarding and OAUTH_UPDATE_PICTURE_ON_LOGIN=false to stop the picture-update code path from firing on existing-user login - the trade-off is that new OAuth-only signups must be provisioned manually and existing users will not see refreshed avatars. As a network-layer compensating control, place the Open WebUI backend behind an egress proxy that blocks outbound HTTP to RFC1918, loopback, link-local (169.254.0.0/16 including 169.254.169.254), and cloud-metadata FQDNs such as metadata.google.internal; the side effect is that legitimate avatar URLs hosted on internal CDNs will also fail. The reporter also documents a code-level workaround: patch _process_picture_url to pass allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS or wrap the call in a manual-follow loop that re-runs validate_url() on every Location header.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2026-55255 HIGH POC
8.4 Jun 19

Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing

Share

CVE-2026-54008 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy