[PR #24587] fix: block private-IP webhook URLs to close SSRF on caller-controlled URL #98767

Open
opened 2026-05-16 01:36:49 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/24587
Author: @Classic298
Created: 5/11/2026
Status: 🔄 Open

Base: devHead: fix/ssrf-webhook-oauth-reranker-validate-url


📝 Commits (2)

  • b5b2114 fix: block private-IP webhook URLs to close SSRF on caller-controlled URL
  • b585aa9 fix: also pass allow_redirects=False on webhook post_webhook session.post

📊 Changes

1 file changed (+17 additions, -2 deletions)

View changed files

📝 backend/open_webui/utils/webhook.py (+17 -2)

📄 Description

post_webhook(url, ...) in utils/webhook.py forwards the URL straight to aiohttp.ClientSession.post with no SSRF gate. The URL is caller-controlled on two surfaces:

  • User notification settings under ENABLE_USER_WEBHOOKS=true — any authenticated user can set the URL their notifications POST to.
  • Automation notification triggers (calendar alerts, etc.).

Without a gate, the URL can target cloud metadata (169.254.169.254 / fd00:ec2::254), localhost-bound services, RFC1918 internal hosts, or any other private address reachable from the server process. Blind SSRF — no response body returned to the caller — but enough to enumerate internal services via response timing / status codes, and on cloud deployments enough to issue requests against IMDSv1 if available.

Call validate_url() at the top of post_webhook. The function blocks private/reserved IPs when ENABLE_RAG_LOCAL_WEB_FETCH is False (the default), is the project's chosen SSRF gate, and is already applied to the equivalent fetch surfaces (retrieval, image-load, OAuth profile picture). Operators who legitimately need to webhook to private IPs (internal monitoring, self-hosted Slack alternatives, etc.) can set ENABLE_RAG_LOCAL_WEB_FETCH=True — same opt-out as the other gated surfaces.

Contributor License Agreement

Note

Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/24587 **Author:** [@Classic298](https://github.com/Classic298) **Created:** 5/11/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `fix/ssrf-webhook-oauth-reranker-validate-url` --- ### 📝 Commits (2) - [`b5b2114`](https://github.com/open-webui/open-webui/commit/b5b21141b424219e1edb7ab97a5024c76995c924) fix: block private-IP webhook URLs to close SSRF on caller-controlled URL - [`b585aa9`](https://github.com/open-webui/open-webui/commit/b585aa95ebdae4c381c2c24463bc9926c3c980df) fix: also pass allow_redirects=False on webhook post_webhook session.post ### 📊 Changes **1 file changed** (+17 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/utils/webhook.py` (+17 -2) </details> ### 📄 Description post_webhook(url, ...) in utils/webhook.py forwards the URL straight to aiohttp.ClientSession.post with no SSRF gate. The URL is caller-controlled on two surfaces: - User notification settings under ENABLE_USER_WEBHOOKS=true — any authenticated user can set the URL their notifications POST to. - Automation notification triggers (calendar alerts, etc.). Without a gate, the URL can target cloud metadata (169.254.169.254 / fd00:ec2::254), localhost-bound services, RFC1918 internal hosts, or any other private address reachable from the server process. Blind SSRF — no response body returned to the caller — but enough to enumerate internal services via response timing / status codes, and on cloud deployments enough to issue requests against IMDSv1 if available. Call validate_url() at the top of post_webhook. The function blocks private/reserved IPs when ENABLE_RAG_LOCAL_WEB_FETCH is False (the default), is the project's chosen SSRF gate, and is already applied to the equivalent fetch surfaces (retrieval, image-load, OAuth profile picture). Operators who legitimately need to webhook to private IPs (internal monitoring, self-hosted Slack alternatives, etc.) can set ENABLE_RAG_LOCAL_WEB_FETCH=True — same opt-out as the other gated surfaces. ### Contributor License Agreement <!-- 🚨 DO NOT DELETE THE TEXT BELOW 🚨 Keep the "Contributor License Agreement" confirmation text intact. Deleting it will trigger the CLA-Bot to INVALIDATE your PR. Your PR will NOT be reviewed or merged until you check the box below confirming that you have read and agree to the terms of the CLA. --> - [x] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-16 01:36:49 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#98767