Aug 7, 2026·6 min read·56 visits
Unauthenticated OS command injection in PHP_CodeSniffer VCS reports due to unescaped filename concatenation in popen() calls.
A critical OS command injection vulnerability exists in PHP_CodeSniffer's VCS blame report modules (Gitblame, Hgblame, Svnblame). Due to inadequate escaping of filenames passed to shell execution wrappers like popen(), an attacker who commits a file with a maliciously crafted name can execute arbitrary commands when the victim generates a blame report.
PHP_CodeSniffer is a highly popular static analysis utility utilized across the software development lifecycle to enforce strict coding standards and maintain consistent code styles. Developers, engineering teams, and automated quality assurance platforms leverage the tool to identify violations in PHP, JavaScript, and CSS codebases.
In addition to parsing syntax and checking style rules, PHP_CodeSniffer provides reporting modules designed to extract version control system (VCS) authorship metadata. These blame reports, specifically Gitblame, Hgblame, and Svnblame, rely on external VCS CLI tools to identify which developer introduced specific lines of code, correlating coding standard violations directly to their authors.
A critical security vulnerability, tracked as CVE-2026-67434, was identified within the VCS blame report generation logic of PHP_CodeSniffer. Categorized under the OS Command Injection (CWE-78) class, the flaw allows unauthenticated attackers to execute arbitrary system commands in the host environment. The execution occurs with the security context and system privileges of the PHP process executing the static analysis run.
The root cause of CVE-2026-67434 is the unescaped concatenation of user-controlled file paths into command-line strings that are passed directly to system shell execution wrappers. When generating authorship reports, PHP_CodeSniffer must run binary utilities like git blame, hg blame, or svn blame on specific files within the scanned repository workspace.
In vulnerable versions of PHP_CodeSniffer, the reporting logic retrieves the name of the file currently being analyzed and interpolates it directly into a shell command template. Although the filename is enclosed in double quotes within the command template, the codebase fails to sanitize or escape the filename argument using native escaping procedures before calling the execution function.
The system commands are launched using PHP's native popen() function, which implicitly invokes the default system shell (such as /bin/sh -c on Unix platforms) to parse and run the command string. Because the shell parses the entire command string dynamically, special characters embedded within the filename double-quotes are interpreted as active shell instructions rather than literal string characters.
Under standard shell parsing rules, characters such as backticks, semicolons, pipe symbols, and subshell invocation characters (such as $()) permit an attacker to break out of the string literal boundary. Consequently, when the shell encounters an embedded subshell statement within the filename argument, it executes the nested payload command prior to spawning the intended VCS execution process.
To illustrate the technical mechanics of the vulnerability, analyze the vulnerable pattern implemented within the Gitblame.php report class prior to remediation:
// Vulnerable command preparation in src/Reports/Gitblame.php
chdir(dirname($filename));
$command = 'git blame --date=short "'.basename($filename).'" 2>&1';
$handle = popen($command, 'r');In this execution path, the variable $filename contains the path of the file currently under analysis, which is directly controlled by the structure of the repository. Because $filename is wrapped in simple double-quotes, an input file named $(id).php generates the final string command git blame --date=short "$(id).php" 2>&1, which immediately triggers the evaluation of the subshell command id upon calling popen().
The secure remediation implemented by the maintainers leverages PHP's native escapeshellarg() function, transforming the unescaped string concatenation into a safely formatted shell argument:
// Remediated command preparation in src/Reports/Gitblame.php
chdir(dirname($filename));
$command = 'git blame --date=short -- '.escapeshellarg(basename($filename)).' 2>&1';
$handle = popen($command, 'r');The escapeshellarg() call wraps the filename argument in single quotes and escapes any pre-existing single quotes within the string, ensuring the shell treats the entire payload strictly as a literal argument. Furthermore, the inclusion of the double-dash -- option terminator instructs the git binary that all subsequent parameters must be processed as positional path arguments, effectively neutralizing potential argument injection payloads that begin with hyphens.
Exploitation of CVE-2026-67434 requires the introduction of a file with a maliciously crafted name into the repository being analyzed by PHP_CodeSniffer. An attacker does not need to compromise the local scanner binary itself; they only need to commit the malicious file structure to the targeted repository.
To conduct the attack, the adversary crafts a filename containing shell execution instructions, such as $(id > exploit_marker).php. The attacker then commits this file and pushes it to a remote repository or submits it as a pull request to a project that utilizes PHP_CodeSniffer for code linting or CI/CD quality checks.
When the victim, which can be an automated build runner or a local developer, initiates a scan on the workspace using one of the blame reports (e.g., via phpcs --report=Gitblame), the static analyzer processes the workspace recursively. Upon reaching the malicious filename, the report generator attempts to extract blame history for it.
During the extraction process, popen() is executed with the unescaped command string, prompting the operating system's command interpreter to evaluate the embedded command substitution payload. This results in the background execution of the shell instructions specified by the attacker, culminating in arbitrary execution within the host machine.
The threat potential of CVE-2026-67434 is classified as High, with a CVSS 4.0 base score of 7.3. The vulnerability provides complete compromise of system confidentiality, integrity, and availability within the execution context of the PHP_CodeSniffer static analyzer.
The primary vector of concern is modern continuous integration (CI) and continuous deployment (CD) pipelines. Many software projects configure automated workflows that execute code quality tools, including PHP_CodeSniffer, on every incoming pull request from untrusted external contributors. An attacker can exploit this pipeline by submitting a pull request containing a maliciously named file, thereby executing code inside the automated runner environment.
Once code execution is obtained in the CI/CD environment, the attacker can leverage the runner's access levels to extract sensitive credentials, environment variables, API keys, or cloud access tokens. In a worst-case scenario, this compromise can serve as a stepping stone for supply chain attacks, allowing malicious code insertion into production builds or artifact repositories. Local developers scanning third-party code are similarly vulnerable to local workstation compromise.
Remediation requires upgrading the squizlabs/php_codesniffer package to version 3.13.6 or 4.0.2 depending on the major version line in use. These versions replace direct string interpolation with robust argument escaping, resolving the direct shell breakout vector.
If immediate upgrading is not possible, organizations should enforce strict input filtering in their build steps or disable the use of VCS blame reports in automated environments. By avoiding the --report=Gitblame, --report=Hgblame, and --report=Svnblame options, the tool will not initiate the vulnerable VCS-querying paths.
A thorough review of the remediation commits shows that while the Gitblame module has been secured with both argument escaping and the -- parameter terminator, the Hgblame and Svnblame modules lack the -- parameter terminator. This leaves those modules theoretically vulnerable to argument injection attacks, where a filename beginning with a hyphen could be interpreted as a command line flag by the mercurial or subversion clients, representing an area of incomplete remediation.
CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
PHP_CodeSniffer PHPCSStandards | < 3.13.6 | 3.13.6 |
PHP_CodeSniffer PHPCSStandards | >= 4.0.0, < 4.0.2 | 4.0.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 |
| Attack Vector | Local |
| CVSS Score | 7.3 |
| EPSS Score | Not established |
| Impact | Arbitrary Code Execution |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The software constructs an OS command using externally-influenced input, but it does not neutralize or incorrectly neutralizes special elements that can modify the intended OS command when it is sent to a downstream component.
Docling prior to version 2.131.0 is vulnerable to arbitrary local code execution during module initialization due to incorrect order of operations in its plugin discovery system. Even when the default option to reject external plugins is active, Docling utilizes Pluggy to scan and import entrypoints before performing namespace validation.
An uncontrolled resource consumption vulnerability exists in the Docling document conversion library. Maliciously structured HTML, JATS, ODS, or BoxNote inputs containing table cells with excessively large 'rowspan' or 'colspan' attribute values trigger algorithmic complexity conditions. This allows unauthenticated remote attackers to initiate resource exhaustion states, crashing or hanging the target document processing pipeline while bypassing configured timeouts.
A Local File Inclusion (LFI) and Arbitrary File Disclosure vulnerability exists in Docling and Docling Slim versions >= 2.16.0 up to 2.131.0. When parsing serialized DoclingDocument structures using the JSON input format, the backend fails to restrict image URI schemes, allowing remote attackers to retrieve local files and verify path existence on the host system during embedded document export.
Docling, a tool for parsing and processing diverse document formats, is vulnerable to arbitrary file read, arbitrary file write, and potential remote code execution (RCE) in versions 2.94.0 through 2.131.0. The vulnerability occurs when applications configure Docling to use the Tectonic engine for rendering TikZ diagrams into images. Because the compilation did not restrict hazardous TeX primitives or sandbox the environment, an attacker can supply crafted documents containing malicious TikZ definitions to access or modify local files and execute arbitrary commands under the privileges of the processing application.
An SSRF guard bypass vulnerability in the Docling document conversion engine allows unauthenticated attackers to bypass internal IP access controls. The vulnerability exists due to a DNS rebinding Time-of-Check Time-of-Use (TOCTOU) condition, URL authority parsing inconsistencies, and unvalidated network requests triggered during headless browser page rendering.
A technical analysis of CVE-2026-105742 (GHSA-p3fw-7699-7926), a sensitive information disclosure vulnerability in the Docling document processing library. Vulnerable versions of Docling indiscriminately forward custom HTTP headers, such as authentication tokens, to arbitrary third-party origins and during cross-origin redirects while fetching remote image assets from untrusted HTML and EPUB documents.