CVE-2026-49358Low· 3.0▾ SunlitPhpWeasyPrint vulnerable to arbitrary file deletion at shutdown via public $temporaryFiles
▾ Sunlit zone — Low / medium · no exploitation signal
impact 16.5 · likelihood 0 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Exploit-prediction probability, daily snapshots since Jul 4.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via GHSA
0.1%
0.1% → 0.1%
AbstractGenerator::$temporaryFiles is a public array, and removeTemporaryFiles() — invoked from __destruct() and from a registered shutdown function — calls unlink() on every entry without verifying that the path is contained within the temporary folder. Any code holding a reference to a generator instance can push an arbitrary path into the array and have it deleted on script shutdown.
This mirrors the KnpLabs/snappy issue GHSA-87qc-37cw-84h4, patched in snappy 1.7.2.
pontedilana/php-weasyprint versions <= 2.5.1.
Patched in: 2.6.0.
src/AbstractGenerator.php:
public array $temporaryFiles = [];
// ...
public function removeTemporaryFiles(): void
{
foreach ($this->temporaryFiles as $file) {
$this->unlink($file);
}
}
No path-containment check: whatever path is present in $temporaryFiles at shutdown is unlinked.
<?php
use Pontedilana\PhpWeasyPrint\Pdf;
$pdf = new Pdf();
$pdf->temporaryFiles[] = '/var/www/html/.env';
// On shutdown, removeTemporaryFiles() deletes /var/www/html/.env.
CWE-73 (External Control of File Name or Path).
Only delete files that actually live inside the temporary folder, comparing canonical (realpath) paths:
public function removeTemporaryFiles(): void
{
$temporaryFolderPath = \realpath($this->getTemporaryFolder());
if (false === $temporaryFolderPath) {
return;
}
$temporaryFolderPath = \rtrim($temporaryFolderPath, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR;
foreach ($this->temporaryFiles as $file) {
$filePath = \realpath($file);
if (false === $filePath || 0 !== \strncmp($filePath, $temporaryFolderPath, \strlen($temporaryFolderPath))) {
continue;
}
$this->unlink($file);
}
}
(The trailing directory separator prevents a sibling folder such as /tmpevil from matching /tmp; strncmp is used instead of str_starts_with to keep PHP 7.4 compatibility.)
Reported upstream to KnpLabs/snappy (GHSA-87qc-37cw-84h4); identified as applicable to pontedilana/php-weasyprint, which mirrors the same code.
pontedilana/php-weasyprint <= 2.5.1Upgrade to a patched release:
pontedilana/php-weasyprint 2.6.0Connected by shared product, vendor, weakness, or advisory.
CVE-2026-49286High· 8.1PhpWeasyPrint vulnerable to PHAR deserialization via output filename (CVE-2023-28115 case-insensitive bypass)
CVE-2026-49359Medium· 6.5PhpWeasyPrint vulnerable to SSRF and local file disclosure via the attachment option
CVE-2026-49260High· 8.2php-weasyprint: shell command injection via configurable WeasyPrint binary path due to inverted is_executable() guard (mirror of KnpLabs/snappy GHSA-vpr4-p6fq-85jc)
CVE-2026-26158High· 7.0A flaw was found in BusyBox
CVE-2026-26157High· 7.0A flaw was found in BusyBox
CVE-2025-68428High· 7.5jsPDF is a library to generate PDFs in JavaScript