/

CVE-2026-110642

Severity:

HIGH RISK

(7.8)

OS Command Injection (CWE-78) in xhtml2pdf Viewer

CVE-2026-110642

Deferred

Vulnerability type

Category:

OS Command Injection

CWE:

CWE-78

Impact:

Arbitrary Command Execution

Severity:

HIGH RISK

(7.8)

CVSS version:

3.1

Catch this CVE while code is being written

Detect vulnerable code directly in pull requests, so CVEs are fixed before merge.

Summary

xhtml2pdf contains an OS command injection vulnerability in pisa.startViewer() because file names are interpolated into a shell command without adequate escaping.

When the viewer option is enabled and an attacker can influence the input file name, crafted metadata may cause commands to execute with the privileges of the invoking process.

xhtml2pdf contains an OS command injection vulnerability in pisa.startViewer() because file names are interpolated into a shell command without adequate escaping.

When the viewer option is enabled and an attacker can influence the input file name, crafted metadata may cause commands to execute with the privileges of the invoking process.

Affected context

The vulnerability affects xhtml2pdf deployments that use the pisa viewer functionality through the -s or --start-viewer option. It becomes risky when an attacker can provide or influence an input file whose name is incorporated into the viewer command, particularly in versions before 0.2.19.

The vulnerability affects xhtml2pdf deployments that use the pisa viewer functionality through the -s or --start-viewer option. It becomes risky when an attacker can provide or influence an input file whose name is incorporated into the viewer command, particularly in versions before 0.2.19.

Exploit preconditions

  • Attack surface: The pisa.startViewer() viewer-launching functionality
  • Required access: Ability to submit or influence an input file name processed by the application
  • Trigger point: Viewer startup when -s or --start-viewer is used
  • Why exploitation is possible: Unescaped file-name data is interpolated into a command executed through the operating system shell
  • Attack surface: The pisa.startViewer() viewer-launching functionality
  • Required access: Ability to submit or influence an input file name processed by the application
  • Trigger point: Viewer startup when -s or --start-viewer is used
  • Why exploitation is possible: Unescaped file-name data is interpolated into a command executed through the operating system shell

Why this happens

The underlying issue is the construction of a shell command using attacker-influenced file-name data without treating that data as strictly non-executable.

Passing interpolated values to os.system() allows shell metacharacters and quoting constructs to alter command interpretation. This maps to CWE-78: Improper Neutralization of Special Elements used in an OS Command, commonly called OS command injection.

The underlying issue is the construction of a shell command using attacker-influenced file-name data without treating that data as strictly non-executable.

Passing interpolated values to os.system() allows shell metacharacters and quoting constructs to alter command interpretation. This maps to CWE-78: Improper Neutralization of Special Elements used in an OS Command, commonly called OS command injection.

Potential impact

  • An attacker may execute arbitrary operating-system commands
  • Commands could run with the privileges of the invoking application
  • The host or container may be compromised
  • Sensitive files or environment data could be exposed
  • The vulnerable process could be used for persistence or lateral movement
  • An attacker may execute arbitrary operating-system commands
  • Commands could run with the privileges of the invoking application
  • The host or container may be compromised
  • Sensitive files or environment data could be exposed
  • The vulnerable process could be used for persistence or lateral movement

General mitigation guidance

Mitigation generally focuses on eliminating shell interpretation and reducing trust in file-name inputs.

Common defensive patterns include:

  • Prefer direct process-execution APIs that pass arguments as structured values rather than invoking a shell
  • Avoid constructing commands through string interpolation
  • Validate file names against a restrictive allowlist of expected characters and formats
  • Treat uploaded or externally supplied file names as untrusted metadata
  • Use fixed executable paths and fixed viewer options where possible
  • Run the rendering process with a dedicated low-privilege account and minimal filesystem permissions
  • Disable viewer-launching functionality when it is not required

Mitigation generally focuses on eliminating shell interpretation and reducing trust in file-name inputs.

Common defensive patterns include:

  • Prefer direct process-execution APIs that pass arguments as structured values rather than invoking a shell
  • Avoid constructing commands through string interpolation
  • Validate file names against a restrictive allowlist of expected characters and formats
  • Treat uploaded or externally supplied file names as untrusted metadata
  • Use fixed executable paths and fixed viewer options where possible
  • Run the rendering process with a dedicated low-privilege account and minimal filesystem permissions
  • Disable viewer-launching functionality when it is not required

How teams detect issues like this

Detection approaches may include:

  • Static analysis rules identifying os.system() or shell execution with concatenated or formatted input
  • Code review checks for file names, paths, or request values embedded in command strings
  • Tests using benign shell-special-character variants to verify that inputs remain data
  • Runtime monitoring for unexpected child processes launched by rendering services
  • Policy enforcement that prohibits shell-based process execution in request-handling code

Automated security review tools can help identify unsafe command construction patterns, but findings should be validated against actual data flow and deployment behavior.

Detection approaches may include:

  • Static analysis rules identifying os.system() or shell execution with concatenated or formatted input
  • Code review checks for file names, paths, or request values embedded in command strings
  • Tests using benign shell-special-character variants to verify that inputs remain data
  • Runtime monitoring for unexpected child processes launched by rendering services
  • Policy enforcement that prohibits shell-based process execution in request-handling code

Automated security review tools can help identify unsafe command construction patterns, but findings should be validated against actual data flow and deployment behavior.

Sources

SourceLink
github.comgithub.com/xhtml2pdf/xhtml2pdf/blob/v0.2.18/xhtml2pdf/pisa.py#L393-L400
github.comgithub.com/xhtml2pdf/xhtml2pdf/commit/f86380dad15b3a6810201d08755a3ee6b19d5063
github.comgithub.com/xhtml2pdf/xhtml2pdf/pull/835
github.comgithub.com/xhtml2pdf/xhtml2pdf/releases/tag/v0.2.19
vulncheck.comvulncheck.com/advisories/xhtml2pdf-before-0.2.19-os-command-injection-via-startviewer-file-name

Frequently asked

questions

It can be remotely exploitable when a service accepts attacker-controlled files or file names and invokes the xhtml2pdf viewer functionality. Exploitability depends on how input files are supplied and whether the viewer option is enabled.

An attacker generally needs the ability to provide or influence an input file name processed by pisa.startViewer(). Authentication may be required by the surrounding application, but the key condition is control over the relevant input.

The safest pattern is to avoid shell interpretation entirely and invoke the intended viewer through a structured process API with fixed executable and argument boundaries. Untrusted file names should also be validated and treated only as data.

Use secure process-execution abstractions, apply least privilege, restrict file-name formats, disable unnecessary command-launching features, and include command-injection checks in code review and automated analysis.

It can be remotely exploitable when a service accepts attacker-controlled files or file names and invokes the xhtml2pdf viewer functionality. Exploitability depends on how input files are supplied and whether the viewer option is enabled.

An attacker generally needs the ability to provide or influence an input file name processed by pisa.startViewer(). Authentication may be required by the surrounding application, but the key condition is control over the relevant input.

The safest pattern is to avoid shell interpretation entirely and invoke the intended viewer through a structured process API with fixed executable and argument boundaries. Untrusted file names should also be validated and treated only as data.

Use secure process-execution abstractions, apply least privilege, restrict file-name formats, disable unnecessary command-launching features, and include command-injection checks in code review and automated analysis.

Find out what's already
exploitable in your codebase.