# Gotenberg has incomplete fix for ExifTool arbitrary file write: case-insensitive bypass and missing HardLink/SymLink tags

Gotenberg's ExifTool metadata blocklist was case-sensitive and missed HardLink/SymLink, letting unauthenticated API users write, move, or link files to arbitrary paths.

- Payout: Research
- Severity: high
- Program: Gotenberg
- Found by: kodareef5
- Disclosed: 2026-04-07
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-qmwh-9m9c-h36m
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-qmwh-9m9c-h36m
- Tags: area:web domain:api domain:web impact:dos impact:integrity kind:research platform:ghsa sev:high tech:go technique:incomplete-fix technique:source-review vuln:misconfiguration vuln:path-traversal

**Target:** Gotenberg HTTP API /forms/pdfengines/metadata/write (ExifTool metadata writer)
**Root cause:** The fix used Go's case-sensitive delete() on exact keys "FileName"/"Directory", but ExifTool parses tag names case-insensitively, so alternate casings bypass the filter. The blocklist also omitted the HardLink and SymLink pseudo-tags.
**Steps:**
1. Send `curl -X POST http://localhost:3000/forms/pdfengines/metadata/write -F files=@sample.pdf -F 'metadata={"filename": "/tmp/evil_bypass.pdf"}'` to move the file via lowercase casing.
2. Send `metadata={"HardLink": "/tmp/hardlink_bypass.pdf"}` to create a hard link at an arbitrary path.
3. Send `metadata={"SymLink": "/tmp/symlink_bypass.pdf"}` to create a symlink at an arbitrary path.
4. Verify inside container: `docker exec gotenberg-poc ls -la /tmp/evil_bypass.pdf /tmp/hardlink_bypass.pdf /tmp/symlink_bypass.pdf` shows the moved file, hard link, and symlink.
**How found:** Reviewed the v8.29.0 fix commit 043b158, noticed the blocklist used Go's case-sensitive delete() while ExifTool is documented as case-insensitive, and that HardLink/SymLink pseudo-tags were absent; confirmed ExifTool case-insensitivity directly with `exiftool -filename=bypassed.pdf test.pdf`.
**Exploitation:** Unauthenticated attacker posts a PDF plus a metadata JSON to the metadata/write endpoint. The go-exiftool library writes `-<key>=<value>` to ExifTool stdin, so `filename`, `HardLink`, or `SymLink` reach ExifTool and cause file rename/move or link creation at attacker-chosen paths within the container filesystem.
**Escalation:** In bare-metal or shared-volume deployments, arbitrary path writes/links can affect other services; in containers limited to DoS via overwriting temp files.
**Insight:** When a fix blocklists names for a downstream tool, match that tool's own parsing semantics (case, aliases, pseudo-tags) rather than the host language's; enumerate the tool's full tag/pseudo-tag set, not just the two tags from the original report.

## Proof of concept (copied exactly from the original report)

**Case-insensitive filename bypass curl request**

```
curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \
      -F files=@sample.pdf \
      -F 'metadata={"filename": "/tmp/evil_bypass.pdf"}'
```

