Gotenberg CVE-2026-45741
HIGHSeverity by source
AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
IsPublicIP in pkg/gotenberg/outbound.go incorrectly classifies IPv6 6to4 / NAT64 / deprecated site-local addresses as public IPs, allowing an unauthenticated attacker to reach internal destinations (e.g., cloud metadata services at 169.254.169.254) via a single crafted DNS AAAA record. This is a variant of CVE-2026-44430 (modelcontextprotocol/registry).
Details
IsPublicIP uses Go stdlib helpers (IsLoopback, IsPrivate, IsLinkLocalUnicast, etc.) to block internal IPs. However, these helpers do not recognize IPv6 prefixes that embed IPv4 addresses:
| Prefix | RFC | Tunnels to |
|---|---|---|
2002::/16 | RFC 3056 (6to4) | IPv4 in bits 16-47 |
64:ff9b::/96 | RFC 6052 (NAT64 well-known) | IPv4 in low 32 bits |
64:ff9b:1::/48 | RFC 8215 (NAT64 local-use) | IPv4 in low 32 bits |
fec0::/10 | RFC 3879 (deprecated site-local) | internal routing |
addr.Unmap() only handles ::ffff:0:0/96 (IPv4-mapped) and has no effect on these prefixes. On dual-stack or NAT64-enabled cloud hosts, the OS kernel transparently routes these addresses to their embedded internal IPv4 destinations.
Vulnerable code (pkg/gotenberg/outbound.go L53-69, commit 93d0103):
func IsPublicIP(addr netip.Addr) bool {
addr = addr.Unmap() // only handles ::ffff:x.x.x.x
switch {
case addr.IsLoopback(), addr.IsPrivate(),
addr.IsLinkLocalUnicast(), ...:
return false
}
return true // 6to4/NAT64/site-local incorrectly reaches here
}PoC
cd poc/
./build.sh
# docker build (~30s)
./run.sh
# docker run - exits with code 1 (bug detected)Expected output: IsPublicIP(2002:a9fe:a9fe::) = true - the function returns true for 3 addresses that wrap 169.254.169.254 (AWS IMDS). Full test file available via GHSA private comment on request.
Impact
An unauthenticated attacker controlling a DNS AAAA record can tunnel gotenberg's outbound HTTP client to AWS/GCP/Azure IMDS (169.254.169.254), leaking IAM credentials. The Chromium URL convert route returns the full response as a PDF (full-read SSRF). Affects all deployments with WithDenyPrivateIPs(true) on dual-stack or NAT64-enabled hosts.
Suggested Fix
Add explicit prefix checks after addr.Unmap():
var blockedIPv6Prefixes = []netip.Prefix{
netip.MustParsePrefix("2002::/16"),
netip.MustParsePrefix("64:ff9b::/96"),
netip.MustParsePrefix("64:ff9b:1::/48"),
netip.MustParsePrefix("fec0::/10"),
}
for _, p := range blockedIPv6Prefixes {
if p.Contains(addr) { return false }
}AnalysisAI
SSRF deny-list bypass in Gotenberg v8 (<= 8.32.0) allows unauthenticated remote attackers to reach internal cloud metadata services (e.g., AWS/GCP/Azure IMDS at 169.254.169.254) by serving a crafted DNS AAAA record containing IPv6 6to4, NAT64, or deprecated site-local prefixes that the IsPublicIP allow-list fails to recognize. Publicly available exploit code exists via the GitHub Security Advisory PoC, and the Chromium URL-convert route returns the upstream response as a PDF, yielding a full-read SSRF that can leak IAM credentials. No vendor-released patch identified at time of analysis (advisory lists no fixed version).
Technical ContextAI
Gotenberg is a Go-based API server (Docker-distributed) that wraps Chromium, LibreOffice, and PDF engines to convert URLs and documents into PDFs. Its outbound HTTP client relies on pkg/gotenberg/outbound.go's IsPublicIP function to enforce WithDenyPrivateIPs(true), but that function uses only Go stdlib helpers (IsLoopback, IsPrivate, IsLinkLocalUnicast) which know nothing about IPv4-embedding IPv6 prefixes defined in RFC 3056 (6to4 2002::/16), RFC 6052 (NAT64 well-known 64:ff9b::/96), RFC 8215 (NAT64 local 64:ff9b:1::/48), and RFC 3879 (deprecated site-local fec0::/10). addr.Unmap() only normalizes ::ffff:0:0/96 mapped addresses, so addresses such as 2002:a9fe:a9fe:: (which embeds 169.254.169.254) fall through to the default-allow branch; on dual-stack or NAT64-enabled cloud hosts the kernel transparently routes these to their embedded IPv4 destination. The root cause maps to CWE-184 (Incomplete List of Disallowed Inputs) - a denylist that omits an exploitable equivalence class.
RemediationAI
No vendor-released patch identified at time of analysis - the GHSA reports fixed version 'None' for github.com/gotenberg/gotenberg/v8, so operators should monitor https://github.com/gotenberg/gotenberg/security/advisories/GHSA-86m8-88fq-xfxp for a tagged release and upgrade as soon as one is published. As compensating controls, apply the upstream-suggested code change locally (extend IsPublicIP in pkg/gotenberg/outbound.go to reject the 2002::/16, 64:ff9b::/96, 64:ff9b:1::/48, and fec0::/10 prefixes after addr.Unmap()), or run the container in an IPv4-only network namespace (e.g., Docker --sysctl net.ipv6.conf.all.disable_ipv6=1 or a Kubernetes pod with single-stack IPv4), which eliminates the kernel's ability to route the tunneled prefixes at the cost of losing legitimate IPv6 outbound conversions. On AWS, enforce IMDSv2 with a hop-limit of 1 to break the credential-theft impact even if SSRF succeeds; on GCP/Azure, restrict the workload's metadata permissions and use egress firewall rules that deny outbound traffic from the Gotenberg pod to 169.254.169.254 and the equivalent IPv6 link-local metadata addresses, accepting that those rules must be maintained alongside the application.
An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl
runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac
Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post
Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build
Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l
Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c
Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.2.169 and Application prior to version 2
An issue in Plone Docker Official Image 5.2.13 (5221) open-source software that could allow for remote code execution du
Tandoor Recipes is an application for managing recipes, planning meals, and building shopping lists. Rated critical seve
Unauthenticated remote code execution in 9router (npm package) versions 0.4.30 through 0.4.36 allows network-adjacent at
Same weakness CWE-184 – Incomplete List of Disallowed Inputs
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-86m8-88fq-xfxp