# PHPUnit has Argument injection via newline in PHP INI values that are forwarded to child processes

PHPUnit forwards INI values to child processes as -d args without neutralizing newlines, letting a crafted phpunit.xml inject auto_prepend_file for RCE in CI.

- Payout: Research
- Severity: high
- Program: PHPUnit
- Found by: kayw-geek, sebastianbergmann, sanmai
- Disclosed: 2026-04-18
- CVE: CVE-2026-41570
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-qrr6-mg7r-m243
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-qrr6-mg7r-m243
- Tags: area:cloud domain:infra impact:integrity impact:rce kind:research platform:ghsa sev:high tech:php technique:source-review vuln:command-injection vuln:crlf-injection vuln:rce

**Target:** PHPUnit JobRunner settingsToParameters() / PHP INI forwarding to child processes
**Root cause:** settingsToParameters() builds `-d name=value` arguments without neutralizing INI metacharacters; PHP's INI parser treats a newline as a directive separator, so a value containing \n is parsed as multiple directives by the child process.
**Steps:**
1. Attacker with write access to phpunit.xml adds `<ini name="x" value="...\nauto_prepend_file=/attacker/payload.php"/>` (newline embedded in value).
2. CI runs PHPUnit against the PR; JobRunner::settingsToParameters() forwards the value as `-d x=...\nauto_prepend_file=...` to the child process.
3. Child PHP parses the newline as a directive separator, applying the injected auto_prepend_file.
4. Child process executes attacker-controlled PHP, yielding RCE in the CI runner.
**How found:** Not stated beyond advisory analysis; reporter noted INI values are forwarded verbatim as -d arguments and that PHP's INI parser treats newline as a directive separator.
**Exploitation:** Poisoned Pipeline Execution: untrusted PR modifies phpunit.xml with a newline-containing INI value; CI executes PHPUnit without isolation, child process loads attacker auto_prepend_file and runs arbitrary code in the runner.
**Escalation:** Injected directives can also set extension, disable_functions, open_basedir; RCE in CI runner can pivot to secrets and pipeline credentials.
**Insight:** When a tool re-serializes config values into `-d name=value` CLI args, check whether the downstream parser (PHP INI) treats newline/`;`/`"` as structural — a single newline turns one directive into many, and auto_prepend_file is the RCE primitive.

