BuildNot yet confirmed elsewhere1 publisher2 min readPublished
CVE-2026-40281 lets a newline in a Gotenberg metadata value move files as root
Gotenberg's 8.30.1 patch validated metadata keys but not values, so CVE-2026-40281 lets unauthenticated callers move files as root. The dev.to write-up of the bug does not name a fixed release, so operators have no confirmed version to move to.
The Engineer · Build desk
Exposure map of CVE-2026-40281. An unauthenticated attacker can move or overwrite files or create symlinks or hardlinks as root. ExifTool runs as root by default. 8.30.1 added a key regex blocking newlines; the value reaches SetString() unchecked. Pseudo-tags -FileName and -SymLink move files.
- capability Unauthenticated attacker Can move or overwrite arbitrary files, or create symlinks or hardlinks, all as root, claim 5
- capability ExifTool in the container Runs as root by default inside the Gotenberg container, claim 12
- constraint Gotenberg 8.30.1 Added key validation in WriteMetadata() using a regex that blocks newlines in a key, claim 3
- contradiction The metadata value Once the key clears validation, the value is handed to SetString() with no check, so argument injection is possible, claim 4
- capability ExifTool pseudo-tags -FileName, -Directory, -SymLink and -HardLink manipulate the filesystem directly, claim 11
| Who | How | Kind | Claim |
|---|---|---|---|
| Unauthenticated attacker | Can move or overwrite arbitrary files, or create symlinks or hardlinks, all as root | capability | 5 |
| ExifTool in the container | Runs as root by default inside the Gotenberg container | capability | 12 |
| Gotenberg 8.30.1 | Added key validation in WriteMetadata() using a regex that blocks newlines in a key | constraint | 3 |
| The metadata value | Once the key clears validation, the value is handed to SetString() with no check, so argument injection is possible | contradiction | 4 |
| ExifTool pseudo-tags | -FileName, -Directory, -SymLink and -HardLink manipulate the filesystem directly | capability | 11 |
What happened
- The earlier flaw, tracked as CVE-2026-42589, was a newline in a metadata key, and Gotenberg 8.30.1 answered it with a regex check on keys.
- The entry point is /forms/pdfengines/metadata/write, which passes each key/value pair through WriteMetadata() to SetString() in the go-exiftool library.
- A value can carry -FileName, -Directory, -SymLink or -HardLink, ExifTool pseudo-tags that manipulate the filesystem directly and are the tags the key check meant to block.
- In the write-up's proof of concept the request returned HTTP 404, and a root-owned copy of the PDF was sitting at /tmp/inject_proof.
Why it matters
- exposure Any path in the container is a target. The attacker picks the destination, and ExifTool runs as root by default, so file permissions inside the container do not limit the move.
- decision With no fixed release named, operators choose between restricting that one route now and waiting for an advisory. The write-up's exploit goes through that route alone.
- constraint On the write-up's setup a successful move returns HTTP 404, so a log search for 200 responses on that route would miss the exploit.
- precedent CVE-2026-42589 covered the key and CVE-2026-40281 covers the value. A patch that validates one field of a pair at the call site leaves the stdin write open to the other.
Gotenberg does not start ExifTool for each request. According to the dev.to write-up, it keeps one process alive in `-stay_open` mode and feeds it over stdin, so each line written there is effectively one command-line argument [8]. The go-exiftool library builds that line as `fmt.Fprintln(e.stdin, "-"+k+"="+str)` [7]. Fprintln only appends a trailing newline, so an embedded one passes through [9].
The 8.30.1 check loops over the keys and rejects any that fail `safeKeyPattern` [3]. The write-up says that part works as intended. The very next step hands the value to `SetString()` with no validation [4]. Send a Title of `test\n-FileName=/tmp/inject_proof` and ExifTool's stdin receives `-Title=test` and then `-FileName=/tmp/inject_proof` [10].
That second line is the same class of injection the key regex was written to stop. The patch guarded one field of a two-field pair, and the other field reaches the same stdin write [14].
The write-up, as supplied, ends mid-sentence in its description of combining the injected tags. The only version it names is 8.30.1, the release that shipped the key-only check [3].
In our view the check belongs where the line is built. A key and a value are two attacker-controlled strings, and the stdin write is the one place both pass through [7]. A newline check on either half at that write would have covered both reports [14].
Until a fixed build is confirmed, we'd keep the metadata route off any network that untrusted clients can reach. The write-up's exploit uses a single route, `/forms/pdfengines/metadata/write` [6]. If your pipeline writes PDF metadata through Gotenberg, that means putting your own authentication in front of it, since the bug needs none [5].
What to watch
- A Gotenberg release or advisory that names the fix for CVE-2026-40281 and says whether it validates values or rejects newlines before the stdin write.
- Any change to the go-exiftool line that writes keys and values to stdin, since that single write is shared by every caller of the library.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence58
- Adoption
- Insufficient
- Hype gap
- Insufficient
- Incentives
- Insufficient
- Confidence62
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
Gotenberg is a Docker-based API server that converts HTML and Office documents into PDFs, and it can write metadata such as title and author into the PDF through an external program called ExifTool.
- [2]
An earlier flaw, a newline inside a metadata key injecting arbitrary arguments into ExifTool, is tracked as CVE-2026-42589.
- [3]
Gotenberg 8.30.1 (commit 405f106) added key validation in WriteMetadata() using safeKeyPattern, a regex that allows only safe characters such as alphanumerics and blocks newlines or '=' in a key.
- [4]
The write-up says the key check works as intended, but once a key clears validation its value is handed to SetString() with no check at all, so the same class of argument injection is possible through a newline in the value.
- [5]
CVE-2026-40281: an unauthenticated attacker can move or overwrite arbitrary files inside the Gotenberg container, or create symlinks or hardlinks at paths of their choosing, all as root.
- [6]
A client sends a PDF plus JSON metadata to /forms/pdfengines/metadata/write; Gotenberg passes it to WriteMetadata() in pkg/modules/exiftool/exiftool.go, which hands each key/value pair to SetString() in the go-exiftool library.
- [7]
go-exiftool writes each key/value pair as one line to the stdin of a running ExifTool process with fmt.Fprintln(e.stdin, "-"+k+"="+str).
- [8]
Gotenberg keeps one ExifTool process running in -stay_open mode and feeds it commands over stdin, so every line written to stdin is effectively one command-line argument.
- [9]
fmt.Fprintln appends a newline after the string it is given and does nothing to stop a newline already inside that string, so a value containing \n sends ExifTool two lines instead of one.
- [10]
A Title value of "test\n-FileName=/tmp/inject_proof" makes ExifTool's stdin receive the two lines -Title=test and -FileName=/tmp/inject_proof.
- [11]
-FileName, -Directory, -SymLink and -HardLink are ExifTool pseudo-tags that do not write metadata but manipulate the filesystem directly; they are the tags the key validation was meant to block.
- [12]
Inside the Gotenberg container, ExifTool runs as root by default.
- [13]
In the write-up's proof of concept, a curl request posting a PDF with a Title value containing a newline and -FileName=/tmp/inject_proof returned HTTP 404, which the write-up reads as the file vanishing from its temp path; ls then showed a root-owned file at /tmp/inject_proof.
- [14]
CVE-2026-42589 (key side) and CVE-2026-40281 (value side) together cover both attacker-controlled halves of the metadata key/value pair.
Sources
1 independent publisher whose own reporting we read for this story.
- dev.toCVE-2026-40281 Explained: A Patch That Guarded "=" on One Side Only
1 article · October 12, 2026
Topics and entities
Follow any of these and your For You feed starts watching them — no settings page required.
Topics
- Container SecurityFollow
- PDF generation servicesFollow
- Argument injection in Git toolingFollow