Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-49358

CVE-2026-49358: PhpWeasyPrint Path Traversal Vulnerability

CVE-2026-49358 is a path traversal vulnerability in PhpWeasyPrint that allows arbitrary file deletion through manipulation of temporary file arrays. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-49358 Overview

PhpWeasyPrint is a PHP library that generates PDFs from URLs or HTML pages by wrapping the WeasyPrint command-line tool. Versions prior to 2.6.0 expose AbstractGenerator::$temporaryFiles as a public array that is consumed by removeTemporaryFiles() during destruction and shutdown. The cleanup routine calls unlink() on every entry without validating that paths reside inside the configured temporary folder. Any code holding a reference to a generator instance can push an arbitrary file path into the array, resulting in deletion of that file when the script terminates. The issue mirrors KnpLabs/snappy advisory GHSA-87qc-37cw-84h4 and is tracked under [CWE-73] (External Control of File Name or Path).

Critical Impact

Local attackers with the ability to influence the $temporaryFiles array can trigger arbitrary file deletion when the PHP process shuts down, potentially impacting application availability and integrity.

Affected Products

  • PhpWeasyPrint versions prior to 2.6.0
  • PHP applications using pontedilana/php-weasyprint for PDF generation
  • Downstream projects sharing the affected AbstractGenerator pattern with KnpLabs/snappy

Discovery Timeline

  • 2026-06-19 - CVE-2026-49358 published to NVD
  • 2026-06-23 - Last updated in NVD database

Technical Details for CVE-2026-49358

Vulnerability Analysis

The flaw resides in AbstractGenerator::removeTemporaryFiles(), which iterates the public $temporaryFiles property and unconditionally calls unlink() on each entry. The method runs from __destruct() and from a registered shutdown function, so cleanup occurs even when the script aborts. Because the property is public, any code path with a reference to a generator instance can append arbitrary paths to the array. Those paths are then deleted with the privileges of the PHP process at shutdown, mapped to weakness [CWE-73].

Root Cause

The root cause is missing path containment validation. The original implementation trusted every value placed in $temporaryFiles and never resolved or compared paths against the generator's temporary directory. Combined with the public visibility of the property, this design allowed external code to inject paths outside the intended cleanup scope.

Attack Vector

Exploitation requires local access and high privileges within the PHP runtime, because the attacker must already be able to execute code that holds a reference to a PhpWeasyPrint generator instance. User interaction is not required. The impact is limited to file deletion, which can degrade integrity and availability of files writable by the PHP process. Network-based exploitation is not described in the advisory.

php
     */
    public function removeTemporaryFiles(): void
    {
+        $temporaryFolderPath = \realpath($this->getTemporaryFolder());
+        if (false === $temporaryFolderPath) {
+            return;
+        }
+        $temporaryFolderPath = \rtrim($temporaryFolderPath, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR;
+
        foreach ($this->temporaryFiles as $file) {
+            // Only delete files actually located inside the temporary folder, so a path
+            // injected into the public $temporaryFiles cannot turn cleanup into an
+            // arbitrary file deletion at shutdown.
+            $filePath = \realpath($file);
+            if (false === $filePath || 0 !== \strncmp($filePath, $temporaryFolderPath, \strlen($temporaryFolderPath))) {
+                continue;
+            }
            $this->unlink($file);
        }
    }

Source: GitHub Commit 6d328ff. The patch resolves the configured temporary folder with realpath() and uses strncmp() to confirm each file path is contained within that folder before calling unlink().

Detection Methods for CVE-2026-49358

Indicators of Compromise

  • Unexpected deletion of files owned by the PHP process user during or shortly after PDF generation requests
  • PHP shutdown errors referencing removeTemporaryFiles() or unlink() against paths outside the configured temporary folder
  • Application logs showing AbstractGenerator instances receiving untrusted input that reaches the $temporaryFiles property

Detection Strategies

  • Audit application code for any write access to $generator->temporaryFiles outside the PhpWeasyPrint library itself
  • Run dependency scanners against composer.lock to flag installations of pontedilana/php-weasyprint below version 2.6.0
  • Review PHP error and access logs for shutdown-time unlink() failures targeting paths outside the temporary directory

Monitoring Recommendations

  • Enable filesystem auditing (for example, auditd on Linux) on directories writable by the PHP service account to capture deletion events
  • Monitor file integrity for critical configuration and data files that the PHP process can reach
  • Track composer dependency drift to ensure the library remains at 2.6.0 or later across environments

How to Mitigate CVE-2026-49358

Immediate Actions Required

  • Upgrade pontedilana/php-weasyprint to version 2.6.0 or later in all environments
  • Review application code for any logic that writes to the public $temporaryFiles property and remove such usage
  • Restrict filesystem permissions for the PHP process user to the minimum set of paths required for operation

Patch Information

The fix is available in PhpWeasyPrint 2.6.0. See the GitHub Release 2.6.0, the security advisory GHSA-5g9f-cwwg-4p8g, and the upstream KnpLabs/snappy advisory GHSA-87qc-37cw-84h4 for full technical context.

Workarounds

  • If patching is not immediately possible, treat the generator instance as untrusted state and ensure no application code mutates $temporaryFiles directly
  • Constrain the temporary folder used by PhpWeasyPrint to a dedicated directory that contains no sensitive files
  • Run the PHP worker under a dedicated low-privilege account so that any unintended unlink() cannot affect files outside the PDF generation scope
bash
# Upgrade PhpWeasyPrint to the patched release
composer require pontedilana/php-weasyprint:^2.6.0
composer update pontedilana/php-weasyprint

# Verify installed version
composer show pontedilana/php-weasyprint | grep versions

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.