GitHub Security Advisory: GHSA-vvj3-c3rp-c85p
Package: phpunit/phpunit (COMPOSER)
Severity: HIGH (CVSS 7.8)
CWE: CWE-502: Deserialization of Untrusted Data
Vulnerable versions: >= 9.0.0, < 9.6.33
Patched in: 9.6.33

Summary: PHPUnit Vulnerable to Unsafe Deserialization in PHPT Code Coverage Handling

Details:
### Overview

A vulnerability has been discovered involving unsafe deserialization of code coverage data in PHPT test execution. The vulnerability exists in the `cleanupForCoverage()` method, which deserializes code coverage files without validation, potentially allowing remote code execution if malicious `.coverage` files are present prior to the execution of the PHPT test.

### Technical Details

**Affected Component:** PHPT test runner, method `cleanupForCoverage()`
**Affected Versions:** <= 8.5.51, <= 9.6.32, <= 10.5.61, <= 11.5.49, <= 12.5.7

### Vulnerable Code Pattern

```php
if ($buffer !== false) {
    // Unsafe call without restrictions
    $coverage = @unserialize($buffer);
}
```

The vulnerability occurs when a `.coverage` file, which should not exist before test execution, is deserialized without the `allowed_classes` parameter restriction. An attacker with local file write access can place a malicious serialized object with a `__wakeup()` method into the file system, leading to arbitrary code execution during test runs with code coverage instrumentation enabled.

### Attack Prerequisites and Constraints

This vulnerability requires **local file write access** to the location where PHPUnit stores or expects code coverage files for PHPT tests. This can occur through:

* **CI/CD Pipeline Attacks:** A malicious pull request that places a `.coverage` file alongside test files, executed when the CI system runs tests using PHPUnit and collects code coverage information
* **Local Development Environment:** An attacker with shell access or ability to write files to the project directory
* **Compromised Dependencies:** A supply chain attack inserting malicious files into a package or monorepo

**Critical Context:** Running test suites from unreviewed pull requests without isolated execution is inherently a code execution risk, independent of this specific vulnerability. This represents a broader class of [Poisoned Pipeline Execution (PPE) attacks](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-04-Poisoned-Pipeline-Execution) affecting CI/CD systems.

### Proposed Remediation Approach

Rather than just silently sanitizing the input via `['allowed_classes' => false]`, the maintainer has chosen to make the anomalous state explicit by treating pre-existing `.coverage` files for PHPT tests as an error condition.

#### Rationale for Error-Based Approach:

1. **Visibility Over Silence:** When an invariant is violated (a `.coverage` file existing before test execution), the error must be visible in CI/CD output, alerting operators to investigate the root cause rather than proceeding with sanitized input
2. **Operational Security:** A `.coverage` file should never exist before tests run, coverage data is generated by executing tests, not sourced from artifacts. Its presence indicates:
    * A malicious actor placed it intentionally
    * Build artifacts from a previous run contaminated the environment
    * An unexpected filesystem