CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-QRR6-MG7R-M243
7.8

GHSA-QRR6-MG7R-M243: Argument Injection and Remote Code Execution in PHPUnit JobRunner

Alon Barad
Alon Barad
Software Engineer

Apr 20, 2026·8 min read·3 visits

PoC Available

Executive Summary (TL;DR)

PHPUnit versions prior to 13.1.6 fail to properly escape INI settings passed to child processes via the command line. Attackers who control configuration values can inject newlines to execute arbitrary files via injected INI directives.

An argument injection vulnerability exists in PHPUnit's JobRunner component due to improper neutralization of metacharacters in PHP INI configuration values. This flaw allows an attacker to inject arbitrary INI directives during process forking, potentially leading to remote code execution within the context of continuous integration environments or testing workers.

Vulnerability Overview

PHPUnit utilizes a JobRunner component to manage process isolation and parallel worker execution during testing. Process isolation ensures that individual test cases do not pollute the shared state of the PHP environment. To maintain consistency across these environments, the parent process extracts its currently active PHP INI configuration and forwards it to the forked child process.

The vulnerability manifests in the transmission of these configuration values. The parent process passes the INI settings as command-line arguments to the PHP CLI executable using the -d name=value format. The application constructs this command string without neutralizing special characters embedded within the configuration values.

Because the PHP CLI parser processes the -d argument sequentially and relies on specific metacharacters for structure, unescaped characters disrupt the intended boundaries of the configuration directive. This constitutes an Argument Injection vulnerability (CWE-88), where untrusted data alters the structure of the command execution sequence.

Attackers who possess the ability to manipulate PHPUnit configuration files or relevant environment variables can leverage this weakness. By introducing specific metacharacters into an INI value, the attacker forces the PHP CLI to interpret subsequent text as an entirely distinct configuration directive, expanding their control over the execution environment.

Root Cause Analysis

The fundamental flaw resides in the absence of boundary protection when constructing the command line for the isolated worker. The JobRunner iterates over the associative array of INI settings and directly concatenates them into the execution string. It assumes that the values are benign scalars that do not contain command-shell or application-specific control characters.

The PHP CLI INI parser treats the -d flag as a mechanism to override configuration directives. During processing, the parser interprets certain characters as structural indicators. A semicolon (;) designates the beginning of a comment, truncating the remainder of the value. Double quotes (") serve as string delimiters, and improper nesting breaks the syntactic validity of the argument.

Crucially, the parser evaluates a newline character (\n or \r) as the termination of the current configuration directive. If a newline appears within the value segment of a -d argument, the parser concludes the processing of the initial directive and evaluates the text following the newline as a completely new INI key-value pair. The application failed to anticipate this behavior and did not implement a sanitization routine.

The diagram above illustrates the data flow. The lack of a sanitization boundary at the JobRunner construction phase permits the injection payload to reach the PHP CLI parser intact. The parser, operating according to its specification, blindly processes the injected directive, instantiating the security failure.

Code Analysis and Patch Verification

Prior to the patch, the JobRunner process constructed the command-line arguments using a direct concatenation pattern. The code extracted the configuration values and appended them with a -d prefix, making no distinction between trusted system values and potentially user-controlled inputs. This direct translation from configuration state to execution arguments created the injection vector.

The remediation, implemented in Pull Request #6592, introduces a conditional quoting and escaping mechanism. The patch analyzes each configuration value prior to concatenation. The analysis checks for the presence of semicolons (;) or double quotes (") within the string. These characters indicate that the value requires structural protection to survive the transition to the child process intact.

When the code detects these metacharacters, it applies a specific sanitization routine. First, the value is encapsulated in double quotes. This encapsulation instructs the CLI parser to treat the entire sequence as a single string literal. Second, any internal double quotes are escaped (converted to \") to prevent premature termination of the string boundary.

This remediation ensures that internal newlines or semicolons are evaluated strictly as string data rather than configuration directives. The encapsulation mechanism safely bounds the configuration value, neutralizing the execution context transition issue. The fix specifically addresses the parser's syntax rules, providing a complete structural defense against the injection technique.

Exploitation Methodology

Exploiting this vulnerability requires the attacker to exert control over a PHP INI setting evaluated by the parent PHPUnit process. The most common vector for this control is the phpunit.xml configuration file. In many continuous integration pipelines, developers or automated systems pull configuration files directly from a source code repository.

An attacker begins the exploit sequence by submitting a malicious pull request or committing code that alters the phpunit.xml file. The attacker targets an arbitrary INI setting, such as memory_limit or error_reporting, and crafts a payload containing a newline character. Following the newline, the attacker appends a dangerous directive, typically auto_prepend_file.

The payload takes the structure memory_limit="128M\nauto_prepend_file=/tmp/exploit.php". When the continuous integration system initiates the testing suite, the parent PHPUnit process loads this configuration. As the process forks to execute isolated tests, the JobRunner concatenates the payload into the child process command line without sanitization.

<!-- Example Malicious phpunit.xml -->
<phpunit bootstrap="vendor/autoload.php">
  <php>
    <ini name="memory_limit" value="128M&#10;auto_prepend_file=/tmp/exploit.php"/>
  </php>
  <!-- Test suites omitted -->
</phpunit>

The child process executes the resulting command. The PHP CLI parser processes the initial memory_limit directive, encounters the newline, and processes the injected auto_prepend_file directive. Upon initialization, the child process immediately executes the PHP code located at /tmp/exploit.php before executing any test logic. This achieves arbitrary code execution within the testing worker.

Impact Assessment

The successful exploitation of this argument injection yields high impact across confidentiality, integrity, and availability. The primary consequence is unauthenticated Remote Code Execution (RCE). By abusing the auto_prepend_file or auto_append_file INI directives, the attacker achieves arbitrary command execution within the context of the underlying operating system user running the PHPUnit process.

The severity of this execution context heavily depends on the execution environment. In typical scenarios, PHPUnit runs within automated Continuous Integration and Continuous Deployment (CI/CD) pipelines. Compromise of a CI/CD runner provides the attacker with a highly privileged network position. The attacker can exfiltrate sensitive environment variables, deployment secrets, database credentials, and proprietary source code.

Furthermore, the attacker can leverage the injection vector to disable existing security controls. Injecting the disable_functions directive with an empty value effectively neutralizes PHP-level security restrictions applied to the parent process. This allows the execution of functions like system(), exec(), or shell_exec() that administrators typically restrict in hardened environments.

The vulnerability is assessed with a CVSS severity of 7.8 (High). While the impact is severe, the attack complexity is elevated by the prerequisite condition: the attacker must secure the ability to influence the PHPUnit configuration file or the environment variables defining INI states. In collaborative development environments utilizing pull requests, this prerequisite is frequently attainable.

Remediation and Mitigation

The definitive resolution for this vulnerability is upgrading the phpunit/phpunit package to version 13.1.6 or later. This release incorporates the necessary structural escaping and quoting mechanisms within the JobRunner component. Organizations utilizing major versions 12 or 11 must verify the availability of backported patches or prioritize migration to a supported release branch.

In environments where immediate upgrading is technically prohibitive, security teams must implement strict validation controls over the phpunit.xml file. Administrators should configure branch protection rules in the source control system to mandate rigorous code review for any modifications to testing configuration files. Pipelines should enforce static analysis to detect newline characters or unexpected INI directives within configuration definitions.

Security engineers can deploy Static Application Security Testing (SAST) tools to proactively identify vulnerable package versions across code repositories. Analyzing dependency lockfiles (composer.lock) provides immediate visibility into the exposure surface. The provided Nuclei template demonstrates a method for automating this discovery process by scanning lockfiles for versions predating the fix.

> [!NOTE] Nuclei Detection Rule
id: GHSA-QRR6-MG7R-M243-Check
info:
  name: PHPUnit Argument Injection Version Check
  severity: high
  description: Checks if the installed version of phpunit/phpunit is vulnerable to INI injection.
file:
  - extensions:
      - lock
    extractors:
      - type: regex
        name: phpunit-version
        regex:
          - '"name": "phpunit/phpunit",\s+"version": "([0-9.]+)"'

Organizations must pair these detections with strict least-privilege principles within the CI/CD environment. Build runners must execute within isolated, ephemeral containers lacking access to production secrets unless strictly necessary. Limiting the execution context ensures that a successful compromise of the runner does not cascade into a broader infrastructure breach.

Official Patches

sebastianbergmannPull Request #6592 introducing conditional quoting and escaping

Technical Appendix

CVSS Score
7.8/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Affected Systems

PHPUnit JobRunner ComponentContinuous Integration Pipelines executing PHPUnitAutomated Testing Workers with process isolation enabled

Affected Versions Detail

Product
Affected Versions
Fixed Version
PHPUnit 13
sebastianbergmann
< 13.1.613.1.6
PHPUnit 12
sebastianbergmann
< 12.x-
PHPUnit 11
sebastianbergmann
< 11.x-
AttributeDetail
CWE IDCWE-88 (Argument Injection or Modification)
Attack VectorLocal / CI Configuration
CVSS Score7.8 (High)
Exploit StatusProof of Concept available
ImpactRemote Code Execution
Affected Componentphpunit/phpunit (JobRunner)

MITRE ATT&CK Mapping

T1059.004Command and Scripting Interpreter: Unix Shell
Execution
T1562.001Impair Defenses: Disable or Modify Tools
Defense Evasion
CWE-88
Argument Injection or Modification

Improper neutralization of argument delimiters in a command line string leads to argument injection.

Vulnerability Timeline

Vulnerability reported/identified by kayw-geek.
2026-04-17
Pull Request #6592 created and merged.
2026-04-18
PHPUnit 13.1.6 released containing the fix.
2026-04-18
GHSA-QRR6-MG7R-M243 published in the GitHub Advisory Database.
2026-04-18

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.