Gotenberg is a widely-used Docker-powered stateless API for generating and manipulating PDFs (deployed across thousands of microservices and SaaS apps for invoice, report, and contract generation). CVE-2026-40281 (CVSS 10.0) reveals a critical vulnerability in the metadata write endpoint: a newline character in a metadata value lets an attacker inject arbitrary ExifTool pseudo-tags, leading to arbitrary file overwrite or symlink/hardlink creation within the container's filesystem.
This is a bypass of the incomplete fix introduced in v8.30.1 (which sanitized keys but left values unsanitized). The patched version is 8.31.0.
Technical Details
How Gotenberg uses ExifTool
Gotenberg delegates PDF metadata manipulation to ExifTool, the reference tool for reading/writing multimedia metadata. The vulnerable endpoint accepts an HTTP request specifying key/value metadata pairs to write:
POST /forms/pdfengines/metadata HTTP/1.1
Content-Type: multipart/form-data; boundary=...
[PDF file]
Title=My Document
Author=John Doe
Internally, Gotenberg builds an ExifTool command and passes key/value pairs via stdin:
exiftool -overwrite_original -@ - input.pdf
The -@ - format tells ExifTool to read arguments one per line from stdin. Gotenberg then writes:
-Title=My Document
-Author=John Doe
The bug
The v8.30.1 fix validated keys for control characters (rejecting \n, \r, etc.). But values remained unsanitized. An attacker submits a value containing a newline:
Title=Document\n-FileName=/etc/passwd
ExifTool then receives on stdin:
-Title=Document
-FileName=/etc/passwd
→ ExifTool interprets the second line as a separate pseudo-tag: -FileName is not a PDF tag, it's an ExifTool pseudo-tag that renames the file to the given path.
Dangerous ExifTool pseudo-tags exposed
| Pseudo-tag | Effect |
|---|---|
-FileName | Renames/moves the processed file to an arbitrary path |
-Directory | Moves the file to an arbitrary directory |
-SymLink | Creates a symlink from the PDF to an arbitrary path |
-HardLink | Creates a hard link to an arbitrary path |
An attacker can:
- Overwrite container configuration files (
/etc/passwd, app configs) - Create a symlink from a sensitive path (
/etc/cron.d/,/proc/self/mem) to an attacker-controlled PDF - Hardlink to privileged files for exfiltration
Characteristics
| Field | Value |
|---|---|
| CVSS 3.1 | 10.0 (CRITICAL) |
| Vector | AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:H |
| CWE | CWE-77 (Command Injection) + CWE-20 (Improper Input Validation) |
| Scope | Changed (S:C) — attack extends beyond the Gotenberg binary to the filesystem |
| Authentication | None |
Affected Products and Versions
| Product | Affected versions | Patched version |
|---|---|---|
| Gotenberg | ≤ 8.30.1 | 8.31.0 |
Note: v8.30.1 itself was an incomplete fix for an earlier issue — hence the urgency of the new patch.
Check your version:
# Docker
docker inspect gotenberg --format '{{.Config.Image}}'
# Or via the health endpoint
curl https://gotenberg.example.com/health
Exploitation and Impact
Exploitation conditions
- Gotenberg reachable via HTTP (often internal in a K8s cluster, but sometimes exposed via Ingress for B2B integrations)
- The metadata write endpoint is unauthenticated by default in Gotenberg
- The attacker can send a PDF + a metadata value containing an injected newline
Concrete impacts
1. Container config overwrite
If Gotenberg runs as root (the common Docker case), the attacker can overwrite /etc/passwd or append to /etc/cron.d/. Persistence depends on container lifespan — on Kubernetes with PVCs, tampering may survive restarts.
2. Escape to host via symlink + volume mount
If Gotenberg has a write-mounted Docker volume (typical: /tmp or a volume for processed PDFs), a CVE-created symlink can point to /host/etc/cron.d/malicious.sh if the volume maps to host filesystem. Kubernetes variant: access to secrets/configmaps mounted as volumes.
3. Cross-tenant PDF theft (multi-tenant)
If Gotenberg processes PDFs for multiple customers (SaaS case), an attacker can create a symlink pointing to another tenant's in-progress PDF and grab it through the pipeline output.
4. Service DoS
Trivial: overwrite the Gotenberg binary itself or its configs → crash and outage.
PoC concept
# Prepare PDF + malicious metadata
curl -X POST "https://gotenberg.example.com/forms/pdfengines/metadata" \
-F "files=@input.pdf" \
-F "metadata={\"Title\":\"Doc\n-FileName=/tmp/owned\"}"
ExifTool then runs the first line (-Title=Doc) followed by the second (-FileName=/tmp/owned), renaming the PDF to /tmp/owned.
Detection and IOCs
Gotenberg logs
# Enable debug mode and hunt suspicious patterns
docker logs gotenberg 2>&1 | grep -iE "exiftool|filename|symlink|directory"
Indicators:
- ExifTool errors on unexpected arguments
- Logs showing absolute paths in metadata values (
/etc,/var,/proc) - Unusual files appearing in the container's filesystem
Container filesystem audit
# Recently modified files
docker exec gotenberg find / -newer /tmp -type f 2>/dev/null | head -20
# Symlinks to sensitive paths
docker exec gotenberg find / -type l -ls 2>/dev/null | grep -E "etc|var|proc"
WAF rule
# Block newlines in metadata values
SecRule ARGS_NAMES "@beginsWith metadata" \
"id:'2026040281',phase:2,deny,status:403,\
chain,\
msg:'Gotenberg CVE-2026-40281 metadata newline injection'"
SecRule ARGS "@rx \\\\n|\\\\r|%0a|%0d" \
"t:none,t:lowercase"
Mitigation and Patch
Immediate action: upgrade
# Docker
docker pull gotenberg/gotenberg:8.31.0
docker compose up -d
# Kubernetes
kubectl set image deployment/gotenberg gotenberg=gotenberg/gotenberg:8.31.0
Workaround if patching is delayed
- Disable the metadata endpoint if unused:
# Gotenberg supports flags to disable routes
command:
- "gotenberg"
- "--api-disable-routes=/forms/pdfengines/metadata"
- Place a proxy/WAF in front that filters
\n,\r,%0a,%0din parameters - Run Gotenberg as non-root (reduced impact if compromised)
- Read-only filesystem for the container:
# docker-compose
services:
gotenberg:
read_only: true
tmpfs:
- /tmp
Long-term hardening
- Authentication on Gotenberg endpoints (auth proxy in front if not natively supported)
- Kubernetes network policy restricting who can reach Gotenberg
- Regular audit of Docker images in production
Why Continuous Monitoring of Docker Microservices Matters
DevOps microservices like Gotenberg, ImageMagick-as-a-service, FFmpeg, Tika are massively deployed internally without dedicated visibility. A CVE like CVE-2026-40281, exploiting an external binary (ExifTool) embedded in the microservice, can fly under the radar of traditional vulnerability scanners that don't inspect embedded binaries in Docker images.
With cveo.tech, inventory your DevOps microservices (PDF generators, image converters, templating engines) and get automatic alerts when a critical CVE targets one of your exact versions — so you stop discovering exploitation after the fact.