Summary
| Field |
Value |
| CVE ID |
CVE-2026-46683 |
| Advisory |
GHSA-c5fp-p67m-gq56 |
| Severity |
High |
| Package |
knplabs/knp-snappy (Composer) |
| Affected |
<= 1.6.0 |
| Fixed in |
>= 1.7.0 |
This is a Server-Side Request Forgery (SSRF) and local file read vulnerability in KnpLabs Snappy, a PHP library that wraps wkhtmltopdf for HTML-to-PDF generation. The flaw lives in the xsl-style-sheet option, which is passed directly to wkhtmltopdf without any URL scheme validation. If an attacker can influence the value of that option, they can point it at internal network resources or at local files using file:// URIs, causing the server to fetch and embed content it should never expose.
Detailed Content
How it works
wkhtmltopdf accepts an --xsl-style-sheet argument that tells it to apply an XSL stylesheet when rendering a document. Snappy passes that argument verbatim to the underlying binary. Prior to version 1.7.0, no validation was performed on the scheme or path of the provided value.
This means that if user-controlled input reaches the xsl-style-sheet option, an attacker can supply:
file:///etc/passwd to read local sensitive files
http://169.254.169.254/latest/meta-data/ to hit cloud metadata endpoints (classic SSRF)
- Any internal service URL that is reachable from the server but should not be accessible from the outside
The risk is amplified significantly when:
- The PHP process (and therefore
wkhtmltopdf) runs as root
- The application is not containerized, or the container has broad filesystem or network access
Root Cause
There is no allowlist or scheme check on the xsl-style-sheet value before it is handed off to the wkhtmltopdf process. The library blindly trusts whatever string is provided.
Fix
Version 1.7.0 introduces an allowlist of accepted URL schemes (http and https by default). Any value that does not match an accepted scheme is rejected before the binary is invoked.
Workaround (if you cannot upgrade immediately)
Never pass raw user input directly to Snappy options. Instead, maintain a server-side map of allowed stylesheets and resolve the user's selection against that map, as shown in the PoC section below.
Proof of Concept
Vulnerable code
<?php
// Attacker sends: GET /generate-pdf?stylesheet=file:///etc/passwd
$stylesheet = $_GET['stylesheet'];
$pdf = new Knp\Snappy\Pdf('/usr/local/bin/wkhtmltopdf');
$pdf->generate('page.html', 'out.pdf', [
'xsl-style-sheet' => $stylesheet,
]);
// wkhtmltopdf receives: --xsl-style-sheet file:///etc/passwd
// The contents of /etc/passwd get embedded into the generated PDF.
Attack scenarios
# Read a local file
?stylesheet=file:///etc/passwd
?stylesheet=file:///var/www/html/.env
# Hit a cloud metadata endpoint (SSRF)
?stylesheet=http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Probe an internal service not exposed to the internet
?stylesheet=http://internal-api.corp/admin/config
Fixed / safe code
<?php
// Allowlist approach (recommended workaround and best practice even after patching)
$allowedStylesheets = [
'invoice' => '/app/xsl/invoice.xsl',
'report' => '/app/xsl/report.xsl',
];
$key = $_GET['stylesheet'] ?? '';
if (!array_key_exists($key, $allowedStylesheets)) {
throw new \RuntimeException('Unknown stylesheet.');
}
$pdf = new Knp\Snappy\Pdf('/usr/local/bin/wkhtmltopdf');
$pdf->generate('page.html', 'out.pdf', [
'xsl-style-sheet' => $allowedStylesheets[$key],
]);
// The user can only select 'invoice' or 'report'.
// Arbitrary paths and URLs never reach wkhtmltopdf.
Upgrading
The cleanest fix is to update the package:
composer require knplabs/knp-snappy:^1.7.0
After upgrading, the library itself will reject any xsl-style-sheet value that does not use an allowed scheme, acting as a safety net even if your application-level validation is incomplete.
Key Takeaways
- Any Snappy-based application on version 1.6.0 or below that passes user input to
xsl-style-sheet is vulnerable.
- The worst-case scenario is full SSRF with internal network access and arbitrary local file disclosure, especially on root-privileged processes.
- Upgrade to 1.7.0 or apply the allowlist workaround immediately.
- Treat all options passed to external binaries (
wkhtmltopdf, wkhtmltoimage, etc.) as an untrusted attack surface, not just the URLs or input documents.