Tech 2 min read

CVE-2026-24765: RCE in PHPUnit's PHPT test runner

IkesanContents

Overview

A remote code execution vulnerability caused by unsafe deserialization (CWE-502) was found in PHPUnit’s PHPT test runner. The CVSS score is 7.8, rated High.

Affected Versions

BranchAffected versionsFixed version
PHPUnit 8<= 8.5.518.5.52
PHPUnit 9<= 9.6.329.6.33
PHPUnit 10<= 10.5.6110.5.62
PHPUnit 11<= 11.5.4911.5.50
PHPUnit 12<= 12.5.712.5.8

The impact range is fairly broad.

Vulnerability Details

The cleanupForCoverage() method in the PHPT test runner deserializes code coverage files without validation.

Specifically, it calls @unserialize($buffer) directly. If a malicious .coverage file contains a serialized object with a __wakeup() method, arbitrary code can run during PHPUnit’s cleanup step.

Attack Scenarios

To exploit this issue, an attacker needs to place a malicious file where coverage data is stored. Likely paths include:

  • CI/CD pipelines: Submit a pull request containing a malicious .coverage file and trigger RCE when tests run
  • Supply chain attacks: Slip the malicious file in through a compromised dependency

CI/CD environments are especially risky because they often hold secrets and deployment keys.

How to Check Whether You Are Affected

Check the installed PHPUnit version in your project.

composer show phpunit/phpunit

If you use Composer 2.4 or later, composer audit can also check known vulnerabilities.

composer audit

If you wire composer audit into CI, it will help catch similar issues automatically in the future as well.

Mitigation

Updating to a fixed version is the top priority.

composer update phpunit/phpunit

At the infrastructure level, the following are also worth doing:

  • Use ephemeral CI/CD runners
  • Apply branch protection rules so suspicious files do not get merged easily
  • Add tamper detection for test artifacts

Reference