Skip to main content

Gotenberg CVE-2026-40893

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

CVSS VectorNVD

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

DescriptionNVD

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). …

Sign in for full analysis, threat intelligence, and remediation guidance.

RemediationAI

Within 24 hours: Identify all Gotenberg 8.x instances in production and confirm whether metadata-accepting endpoints are exposed to untrusted networks. Within 7 days: Implement network-level access controls to restrict metadata endpoints to authenticated internal services only; disable or restrict metadata input parameters where not required for business operations. …

Sign in for detailed remediation steps.

Share

CVE-2026-40893 vulnerability details – vuln.today

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