The default deny-lists used by Gotenberg's downloadFrom feature and webhook feature are bypassable. Because the filter is regex-based and case-sensitive, an unauthenticated attacker can supply URLs such as http://[::ffff:127.0.0.1]:... and reach loopback or private HTTP services that the default deny-list is intended to block. This crosses a real security boundary because an external caller can force the server to make outbound requests to internal-only targets.
The issue originates from the shipped default deny-list regexes and the way those regexes are applied:
pkg/modules/api/api.go:198-200 defines the default api-download-from-deny-list.pkg/modules/webhook/webhook.go:41-43 defines the default webhook-deny-list.pkg/gotenberg/filter.go:20-69 evaluates those patterns with regexp2 using case-sensitive matching.The attacker-controlled URL then reaches outbound request sinks:
pkg/modules/api/context.go:208-282
downloadFrom.gotenberg.FilterDeadline(...).retryablehttp.NewRequest(...) and client.Do(...).pkg/modules/webhook/middleware.go:99-217
Gotenberg-Webhook-Url and Gotenberg-Webhook-Events-Url.gotenberg.FilterDeadline(...).client for outbound delivery.pkg/modules/webhook/client.go:39-152
pkg/modules/webhook/client.go:155-216
Why the bypass works:
http:// and https:// prefixes.http://[::ffff:127.0.0.1]:18081/....8.32.0Exploitability
AV:NAC:LPR:NUI:NScope
S:UImpact
C:HI:HA:L9.4/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L