CVE-2026-119193
PHPUnit vulnerable to code execution by other local users via shared temporary directory in PHPT code coverage handling
PHPUnit is a testing framework for PHP. From 13.4.0 until 13.4.4, the TestCase::coverageFilesDirectory() logic in src/Runner/Phpt/TestCase.php creates temporary files for PHPT code coverage in a predictable phpunit-phpt directory under sys_get_temp_dir() and reuses that directory without verifying its ownership or permissions. On multi-user systems with a shared temporary path, a local attacker who creates the directory before the developer runs PHPT tests with code coverage can replace the generated job file before the child process executes it with require, allowing arbitrary code execution with the developer's privileges while the test and coverage report appear successful. PHPUnit 12.5 and earlier, default macOS and Windows configurations with per-user temporary directories, and single-user environments where another user cannot create files in the temporary path are not affected. This issue is fixed in 13.4.4.
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- Passive
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
5.4
PHPUnit vulnerable to code execution by other local users via shared temporary directory in PHPT code coverage handling
PHPUnit is a testing framework for PHP. From 13.4.0 until 13.4.4, the TestCase::coverageFilesDirectory() logic in src/Runner/Phpt/TestCase.php creates temporary files for PHPT code coverage in a predictable phpunit-phpt directory under sys_get_temp_dir() and reuses that directory without verifying its ownership or permissions. On multi-user systems with a shared temporary path, a local attacker who creates the directory before the developer runs PHPT tests with code coverage can replace the generated job file before the child process executes it with require, allowing arbitrary code execution with the developer's privileges while the test and coverage report appear successful. PHPUnit 12.5 and earlier, default macOS and Windows configurations with per-user temporary directories, and single-user environments where another user cannot create files in the temporary path are not affected. This issue is fixed in 13.4.4.
- Record
CVE-2026-119193- CVSS 4.0
- 5.4 Medium
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-379
- Updated
- 2026-11-02
EUVDEUVD-2026-113349
5.4
PHPUnit is a testing framework for PHP. From 13.4.0 until 13.4.4, the TestCase::coverageFilesDirectory() logic in src/Runner/Phpt/TestCase.php creates temporary files for PHPT code coverage in a predictable phpunit-phpt directory under sys_get_temp_dir() and reuses that directory without verifying its ownership or permissions. On multi-user systems with a shared temporary path, a local attacker who creates the directory before the developer runs PHPT tests with code coverage can replace the generated job file before the child process executes it with require, allowing arbitrary code execution with the developer's privileges while the test and coverage report appear successful. PHPUnit 12.5 and earlier, default macOS and Windows configurations with per-user temporary directories, and single-user environments where another user cannot create files in the temporary path are not affected. This issue is fixed in 13.4.4.
- Record
EUVD-2026-113349- CVSS 4.0
- 5.4 Medium
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-9vw2-f4vp-x7gf
5.4
PHPUnit vulnerable to code execution by other local users via shared temporary directory in PHPT code coverage handling
Summary
When PHPT tests are run with code coverage, PHPUnit 13.4.0 to 13.4.3 writes the code of each PHPT test to a directory with a fixed name below the operating system's path used for temporary files, for instance /tmp/phpunit-phpt on Linux, and executes it from there. PHPUnit uses this directory even when it was created by another user.
On a system where the path used for temporary files is shared between users, another local user can create this directory before the developer runs PHPUnit, replace the code of a PHPT test before it is executed, and thereby execute arbitrary code with the privileges of the developer. The test still passes and the code coverage report is complete, so the attack is not visible.
The impact is full code execution as the user who runs PHPUnit. The likelihood is low: the attacker needs an account on the same system and must create the directory before the developer runs PHPT tests with code coverage. macOS and Windows use per-user temporary directories by default and are not affected in their default configuration. PHPUnit 12.5 and earlier are not affected.
Details
When code coverage is collected for a PHPT test, PHPUnit writes two temporary files: a .php file with the code of the PHPT test (the "job" file), which the child process executes, and a .coverage file, to which the child process writes the code coverage data it collected.
Since PHPUnit 13.4.0, these files are created in a directory with a fixed name:
TestCase::coverageFilesDirectory()returnssys_get_temp_dir() . '/phpunit-phpt'- The constructor names the files
phpunit_phpt_<random>.phpandphpunit_phpt_<random>.coveragein this directory
Before a PHPT test is run with code coverage, this directory is created using Filesystem::createDirectory(). Filesystem::createDirectory() returns true when the directory already exists, without checking its owner or its permissions. When it does not exist, it is created with mode 0777 (subject to the umask).
Renderer::renderForCoverage() then writes the job file using file_put_contents(). The child process loads Composer's autoloader, the bootstrap script, and the code coverage driver, and then executes the job file using require.
When another user created the directory, that user owns it. The owner of a directory can list its contents and rename, delete, or replace every file in it, regardless of who owns the file. The directory does not have the sticky bit set, so protections such as Linux's fs.protected_regular and fs.protected_symlinks do not apply either. The random part of the file names therefore does not prevent the attack: the attacker waits for the job file to appear, renames it, and puts a file with their own code in its place. The attacker's code can then execute the original job file, so that the test passes and the code coverage report is complete.
The .coverage file can be replaced in the same way. TestCase::cleanupForCoverage() only allows objects of PHPUnit's class for raw code coverage data to be unserialized from it, so this only allows the falsification of code coverage data.
After the test, PHPUnit deletes both files, but not the directory. Once PHPUnit has created the directory for the developer, other users cannot write to it, unless the developer's umask…
- Record
GHSA-9vw2-f4vp-x7gf- CVSS 4.0
- 5.4 Medium
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-379
- Updated
- 2026-11-02
NVD
5.4
PHPUnit is a testing framework for PHP. From 13.4.0 until 13.4.4, the TestCase::coverageFilesDirectory() logic in src/Runner/Phpt/TestCase.php creates temporary files for PHPT code coverage in a predictable phpunit-phpt directory under sys_get_temp_dir() and reuses that directory without verifying its ownership or permissions. On multi-user systems with a shared temporary path, a local attacker who creates the directory before the developer runs PHPT tests with code coverage can replace the generated job file before the child process executes it with require, allowing arbitrary code execution with the developer's privileges while the test and coverage report appear successful. PHPUnit 12.5 and earlier, default macOS and Windows configurations with per-user temporary directories, and single-user environments where another user cannot create files in the temporary path are not affected. This issue is fixed in 13.4.4.
- Record
CVE-2026-119193- CVSS 4.0
- 5.4 Medium
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-379
- Updated
- 2026-11-02
OSV
5.4
PHPUnit vulnerable to code execution by other local users via shared temporary directory in PHPT code coverage handling
PHPUnit is a testing framework for PHP. From 13.4.0 until 13.4.4, the TestCase::coverageFilesDirectory() logic in src/Runner/Phpt/TestCase.php creates temporary files for PHPT code coverage in a predictable phpunit-phpt directory under sys_get_temp_dir() and reuses that directory without verifying its ownership or permissions. On multi-user systems with a shared temporary path, a local attacker who creates the directory before the developer runs PHPT tests with code coverage can replace the generated job file before the child process executes it with require, allowing arbitrary code execution with the developer's privileges while the test and coverage report appear successful. PHPUnit 12.5 and earlier, default macOS and Windows configurations with per-user temporary directories, and single-user environments where another user cannot create files in the temporary path are not affected. This issue is fixed in 13.4.4.
- Record
CVE-2026-119193- CVSS 4.0
- 5.4 Medium
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-379
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-119193
5.4
PHPUnit is a testing framework for PHP. From 13.4.0 until 13.4.4, the TestCase::coverageFilesDirectory() logic in src/Runner/Phpt/TestCase.php creates temporary files for PHPT code coverage in a predictable phpunit-phpt directory under sys_get_temp_dir() and reuses that directory without verifying its ownership or permissions. On multi-user systems with a shared temporary path, a local attacker who creates the directory before the developer runs PHPT tests with code coverage can replace the generated job file before the child process executes it with require, allowing arbitrary code execution with the developer's privileges while the test and coverage report appear successful. PHPUnit 12.5 and earlier, default macOS and Windows configurations with per-user temporary directories, and single-user environments where another user cannot create files in the temporary path are not affected. This issue is fixed in 13.4.4.
- Record
DEBIAN-CVE-2026-119193- CVSS 4.0
- 5.4 Medium
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
OSVGHSA-9vw2-f4vp-x7gf
5.4
PHPUnit vulnerable to code execution by other local users via shared temporary directory in PHPT code coverage handling
Summary
When PHPT tests are run with code coverage, PHPUnit 13.4.0 to 13.4.3 writes the code of each PHPT test to a directory with a fixed name below the operating system's path used for temporary files, for instance /tmp/phpunit-phpt on Linux, and executes it from there. PHPUnit uses this directory even when it was created by another user.
On a system where the path used for temporary files is shared between users, another local user can create this directory before the developer runs PHPUnit, replace the code of a PHPT test before it is executed, and thereby execute arbitrary code with the privileges of the developer. The test still passes and the code coverage report is complete, so the attack is not visible.
The impact is full code execution as the user who runs PHPUnit. The likelihood is low: the attacker needs an account on the same system and must create the directory before the developer runs PHPT tests with code coverage. macOS and Windows use per-user temporary directories by default and are not affected in their default configuration. PHPUnit 12.5 and earlier are not affected.
Details
When code coverage is collected for a PHPT test, PHPUnit writes two temporary files: a .php file with the code of the PHPT test (the "job" file), which the child process executes, and a .coverage file, to which the child process writes the code coverage data it collected.
Since PHPUnit 13.4.0, these files are created in a directory with a fixed name:
TestCase::coverageFilesDirectory()returnssys_get_temp_dir() . '/phpunit-phpt'- The constructor names the files
phpunit_phpt_<random>.phpandphpunit_phpt_<random>.coveragein this directory
Before a PHPT test is run with code coverage, this directory is created using Filesystem::createDirectory(). Filesystem::createDirectory() returns true when the directory already exists, without checking its owner or its permissions. When it does not exist, it is created with mode 0777 (subject to the umask).
Renderer::renderForCoverage() then writes the job file using file_put_contents(). The child process loads Composer's autoloader, the bootstrap script, and the code coverage driver, and then executes the job file using require.
When another user created the directory, that user owns it. The owner of a directory can list its contents and rename, delete, or replace every file in it, regardless of who owns the file. The directory does not have the sticky bit set, so protections such as Linux's fs.protected_regular and fs.protected_symlinks do not apply either. The random part of the file names therefore does not prevent the attack: the attacker waits for the job file to appear, renames it, and puts a file with their own code in its place. The attacker's code can then execute the original job file, so that the test passes and the code coverage report is complete.
The .coverage file can be replaced in the same way. TestCase::cleanupForCoverage() only allows objects of PHPUnit's class for raw code coverage data to be unserialized from it, so this only allows the falsification of code coverage data.
After the test, PHPUnit deletes both files, but not the directory. Once PHPUnit has created the directory for the developer, other users cannot write to it, unless the developer's umask…
- Record
GHSA-9vw2-f4vp-x7gf- CVSS 4.0
- 5.4 Medium
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-379
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
phpunit/phpunitPackagist |
13.4.0 up to 13.4.4 | 13.4.4 |
phpunitDebian:14 |
before 13.4.5+ds-1, plus listed versions 11.5.19-112.0.10-112.0.2-112.0.3-112.0.4-1 Show 45 moreShow less12.0.5-112.0.7-112.0.7-212.0.8-112.0.9-112.1.0-112.1.2-112.1.3-112.1.4-112.1.5-112.1.6-112.2.1-112.2.2-112.2.3-112.2.5-112.2.6-112.2.7-112.3.0-112.3.11-112.3.12-112.3.14-112.3.15-112.3.15-212.3.3-112.3.4-112.3.5-112.3.6-112.3.7-112.3.8-112.4.0-112.4.1-112.4.2-112.4.3-112.4.4-112.4.5-112.5.1-112.5.2-112.5.3-112.5.4-112.5.5-112.5.6-112.5.7-112.5.8-112.5.9-113.0.0-1 |
13.4.5+ds-1 |
phpunit/phpunitPackagist |
13.4.0 up to 13.4.4, plus listed versions 13.4.113.4.213.4.3 |
13.4.4 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-119193 is a medium vulnerability (CVSS 5.4) in Sebastianbergmann Phpunit, published October 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.11%, the 1st percentile. Fixed in phpunit/phpunit 13.4.4.
References
github.com/sebastianbergmann/phpunit/security/advisories/GHSA-9vw2-f4vp-x7gf
github.com/sebastianbergmann/phpunit/commit/ae31c78a86e9d6c641497bacf47462d7bb7d7f34
github.com/sebastianbergmann/phpunit/releases/tag/13.4.4
nvd.nist.gov/vuln/detail/CVE-2026-119193
github.com/FriendsOfPHP/security-advisories/blob/master/phpunit/phpunit/CVE-2026-119193.yaml
github.com/advisories/GHSA-9vw2-f4vp-x7gf
github.com/CVEProject/cvelistV5/tree/main/cves/2026/119xxx/CVE-2026-119193.json
security-tracker.debian.org/tracker/CVE-2026-119193
github.com/sebastianbergmann/phpunit
Left out here: 39 versions and the rest of 2 source descriptions. The JSON record has them.