dompdf/dompdf · error · Dompdf\Exception

Permission denied on $file. The communication protocol is no

Error message

Permission denied on $file. The communication protocol is not supported.

What it means

loadHtmlFile() enforces a protocol whitelist before any I/O: the URI's scheme must be a key of Options::allowedProtocols (defaults: data://, file://, http://, https://). Any other scheme — or a scheme an administrator removed while hardening dompdf against SSRF/LFI — throws this permission error immediately. It is a security control, not an incidental failure.

Source

Thrown at src/Dompdf.php:357

     *
     * Parse errors are stored in the global array `$_dompdf_warnings`.
     *
     * @param string      $file     A filename or URL to load.
     * @param string|null $encoding Encoding of the file.
     */
    public function loadHtmlFile($file, $encoding = null)
    {
        $this->setPhpConfig();

        if (!$this->protocol && !$this->baseHost && !$this->basePath) {
            [$this->protocol, $this->baseHost, $this->basePath] = Helpers::explode_url($file);
        }
        $protocol = strtolower($this->protocol);
        $uri = Helpers::build_url($this->protocol, $this->baseHost, $this->basePath, $file, $this->options->getChroot());

        $allowed_protocols = $this->options->getAllowedProtocols();
        if (!array_key_exists($protocol, $allowed_protocols)) {
            throw new Exception("Permission denied on $file. The communication protocol is not supported.");
        }

        if ($protocol === "file://") {
            $ext = strtolower(pathinfo($uri, PATHINFO_EXTENSION));
            if (!in_array($ext, $this->allowedLocalFileExtensions)) {
                throw new Exception("Permission denied on $file: The file extension is forbidden.");
            }
        }

        foreach ($allowed_protocols[$protocol]["rules"] as $rule) {
            [$result, $message] = $rule($uri);
            if (!$result) {
                throw new Exception("Error loading $file: $message");
            }
        }

        [$contents, $http_response_header] = Helpers::getFileContent($uri, $this->options->getHttpContext());
        if ($contents === null) {

View on GitHub (pinned to b14267808b)

Solutions

  1. Extend the whitelist deliberately: $options->setAllowedProtocols([...]) — note it REPLACES the map, so include every protocol you need with their rules.
  2. Or fetch the document yourself (curl/Guzzle) and pass the body to $dompdf->loadHtml($html) — this respects app-level network controls instead of dompdf's.
  3. If remote loading is not required, keep it disabled and generate/load local HTML.

Example fix

// before
$dompdf->loadHtmlFile('ftp://example.com/report.html'); // throws: ftp not allowed

// after: either whitelist the protocol
$dompdf->getOptions()->setAllowedProtocols([
    'data://' => ['rules' => []],
    'file://' => ['rules' => []],
    'http://' => ['rules' => []],
    'https://' => ['rules' => []],
    'ftp://' => ['rules' => []],
]);

// or bypass with explicit fetching
$dompdf->loadHtml(file_get_contents_curl('ftp://example.com/report.html'));
Defensive patterns

Strategy: validation

Validate before calling

$scheme = strtolower(parse_url($file, PHP_URL_SCHEME) . '://');
$allowed = $dompdf->getOptions()->getAllowedProtocols();
if (!array_key_exists($scheme, $allowed)) {
    throw new InvalidArgumentException("Protocol not allowed by dompdf config: $file");
}
$dompdf->loadHtmlFile($file);

Try / catch

try {
    $dompdf->loadHtmlFile($file);
} catch (\Dompdf\Exception $e) {
    if (strpos($e->getMessage(), 'communication protocol is not supported') !== false) {
        $dompdf->loadHtml(file_get_contents_via_app_client($file)); // app-controlled fetch
    }
}

Prevention

When it happens

Trigger: $dompdf->loadHtmlFile('ftp://server/doc.html') or any wrapper outside the whitelist; a deployment calls setAllowedProtocols() with only file:// (anti-SSRF hardening) while application code still loads http(s):// URLs; custom stream wrappers used as the document source.

Common situations: Hardening dompdf after security guidance (removing remote protocols), then legacy features that render remote pages break; passing wrapper-prefixed paths like phar:// or php://temp; inconsistent configuration between staging and production.

Related errors


AI-assisted analysis of dompdf/dompdf@b14267808b (2026-08-21). Data as JSON: /api/errors/c7774251cae14447. Report an issue: GitHub.