wkhtmltopdf today · Security

wkhtmltopdf CVE-2022-35583: what to do

CVE-2022-35583, rated 9.8 (critical) by the NVD on 22 August 2022: wkhtmltopdf 0.12.6 lets the HTML it renders reach internal addresses, for instance through an iframe. A server-side request forgery (SSRF) that no release will fix: wkhtmltopdf is archived.

Who is exposed

Any server that converts HTML holding text it does not control: a customer’s name, an address, a comment. Left unescaped, that text can carry an <iframe> or an <img> pointing to http://169.254.169.254/ (cloud metadata) or to a service on localhost. The conversion then sends the request from inside the network.

What pdfkiln does

The earlier flaw, CVE-2020-21365 (rated 7.5: reading local files in wkhtmltopdf 0.12.5 and before), was closed by 0.12.6’s default, which pdfkiln keeps.

Turn the option on

On the command line:

wkhtmltopdf --kiln-block-private-network page.html page.pdf

With pdfkit (Python), in the options:

pdfkit.from_string(html, 'out.pdf', options={'kiln-block-private-network': ''})

knp-snappy, and the libraries that refuse options they do not know, get a script that adds it, in place of the program:

printf '#!/bin/sh\nexec /usr/bin/wkhtmltopdf --kiln-block-private-network "$@"\n' \
  | sudo tee /usr/local/bin/wkhtmltopdf-safe > /dev/null
sudo chmod +x /usr/local/bin/wkhtmltopdf-safe
$pdf = new Knp\Snappy\Pdf('/usr/local/bin/wkhtmltopdf-safe');

The script passes everything else on: wkhtmltopdf-safe --version answers as wkhtmltopdf does.

And in the templates

The cause stays in the template: text that comes from users must be escaped there, as most template engines of web frameworks do by default. The option is the safety net.