fix: Support allowlisted private API inbox webhooks (#14548)

Self-hosted installations can now opt SafeFetch into private-network
access after SSRF hardening. The default remains unchanged: private IP
destinations are blocked unless the instance owner explicitly enables
private-network requests with `SAFE_FETCH_ALLOW_PRIVATE_NETWORK=true`.

Fixes https://linear.app/chatwoot/issue/CW-7131
Fixes https://github.com/chatwoot/chatwoot/issues/14489
Fixes https://github.com/chatwoot/chatwoot/issues/14494

## How to use

For self-hosted installations that need API inbox webhooks, or other
SafeFetch-backed requests, to call trusted private services, enable
private-network access with a single environment variable:

```bash
SAFE_FETCH_ALLOW_PRIVATE_NETWORK=true
```

This is disabled by default. Enable it only when the instance owner
controls the deployment network and trusts the configured URLs.
This commit is contained in:
Vishnu Narayanan
2026-05-26 17:03:19 +05:30
committed by GitHub
parent b981ba766f
commit 7c16071fc7
6 changed files with 164 additions and 4 deletions
+6 -4
View File
@@ -29,18 +29,20 @@ class SafeFetch::Fetcher
end
def stream_response(tempfile)
response = nil
bytes_written = 0
SsrfFilter.public_send(options.method, options.url, **options.request_options) do |res|
response = res
perform_request do |res|
next unless res.is_a?(Net::HTTPSuccess)
validate_content_type!(res['content-type'])
bytes_written = write_response_body(res, tempfile, bytes_written)
end
end
response
def perform_request(&)
return SafeFetch::PrivateNetworkRequest.new(options).perform(&) if SafeFetch.allow_private_network?
SsrfFilter.public_send(options.method, options.url, **options.request_options, &)
end
def validate_content_type!(content_type)