Aug 7, 2026·6 min read·0 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.
An authenticated stored Cross-Site Scripting (XSS) vulnerability exists in the Control Panel helper of Craft CMS before version 5.10.8. Due to lack of HTML entity encoding within the elementLabelHtml method, unescaped draft names are rendered directly into administrative interfaces.
A path traversal vulnerability exists in the local filesystem driver of Craft CMS. Due to validation occurring before path normalization, directory containment checks can be bypassed by utilizing specific protocol schemes like 'file://' along with directory traversal sequences. This allows authenticated users with administrative privileges to access or manipulate files outside the defined storage root directory.
An authorization bypass vulnerability in Craft CMS allows unauthenticated or low-privileged users to query and obtain sensitive time-series user registration counts and demographic metrics. This is due to a missing authorization check inside the actionGetNewUsersData endpoint of the ChartsController class.
An authenticated information disclosure vulnerability in Craft CMS allows high-privilege administrators to extract sensitive environment variables, including the CRAFT_SECURITY_KEY and database credentials, using a blind error-based template injection attack within element select condition rules.
A protocol-parsing vulnerability in the pure-Python HTTP/2 library 'h2' (versions <= 4.4.0) allows unauthenticated remote attackers to perform HTTP Request Smuggling (CWE-444). The vulnerability exists because the library does not validate the uniqueness of 'Host' headers in incoming HTTP/2 request streams. When an upstream gateway parses such requests and downgrades them to HTTP/1.1 for internal backend servers, the resulting stream contains duplicate Host headers, which leads to parsing inconsistency and potential bypass of security filters.
An information disclosure vulnerability in Craft CMS allows users with administrative or non-sandboxed template-authoring privileges to read arbitrary system and configuration files. The issue stems from an incomplete class instantiation blocklist in the Twig template extension, which omitted PHP's built-in SplFileObject class.