{"id":"CVE-2026-24765","aliases":["GHSA-vvj3-c3rp-c85p"],"url":"https://o3.security/vulnerability/CVE-2026-24765","summary":"PHPUnit Vulnerable to Unsafe Deserialization in PHPT Code Coverage Handling","details":"### Overview\n\nA 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.\n\n### Technical Details\n\n**Affected Component:** PHPT test runner, method `cleanupForCoverage()`\n**Affected Versions:** <= 8.5.51, <= 9.6.32, <= 10.5.61, <= 11.5.49, <= 12.5.7\n\n### Vulnerable Code Pattern\n\n```php\nif ($buffer !== false) {\n    // Unsafe call without restrictions\n    $coverage = @unserialize($buffer);\n}\n```\n\nThe 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.\n\n### Attack Prerequisites and Constraints\n\nThis vulnerability requires **local file write access** to the location where PHPUnit stores or expects code coverage files for PHPT tests. This can occur through:\n\n* **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\n* **Local Development Environment:** An attacker with shell access or ability to write files to the project directory\n* **Compromised Dependencies:** A supply chain attack inserting malicious files into a package or monorepo\n\n**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.\n\n### Proposed Remediation Approach\n\nRather 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.\n\n#### Rationale for Error-Based Approach:\n\n1. **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\n2. **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:\n    * A malicious actor placed it intentionally\n    * Build artifacts from a previous run contaminated the environment\n    * An unexpected filesystem state requiring investigation\n3. **Defense-in-Depth Principle:** Protecting a single deserialization call does not address the fundamental attack surface. Proper mitigations for PPE attacks lie outside PHPUnit's scope:\n    * Isolate CI/CD runners (ephemeral, containerized environments)\n    * Restrict code execution on protected branches\n    * Scan pull requests and artifacts for tampering\n    * Use branch protection rules to prevent unreviewed code execution\n\n### Severity Classification\n\n* **Attack Vector (AV):** Local (L) — requires write access to the file system where tests execute\n* **Attack Complexity (AC):** Low (L) — exploitation is straightforward once the malicious file is placed\n* **Privileges Required (PR):** Low (L) — PR submitter status or contributor role provides sufficient access\n* **User Interaction (UI):** None (N) — automatic execution during standard test execution\n* **Scope (S):** Unchanged (U) — impact remains within the affected test execution context\n* **Confidentiality Impact (C):** High (H) — full remote code execution enables complete system compromise\n* **Integrity Impact (I):** High (H) — arbitrary code execution allows malicious modifications\n* **Availability Impact (A):** High (H) — full code execution permits denial-of-service actions\n\n### Mitigating Factors (Environmental Context)\n\nOrganizations can reduce the effective risk of this vulnerability through proper CI/CD configuration:\n\n* **Ephemeral Runners:** Use containerized, single-use CI/CD runners that discard filesystem state between runs\n* **Code Review Enforcement:** Require human review and approval before executing code from pull requests\n* **Branch Protection:** Enforce branch protection rules that block unreviewed code execution\n* **Artifact Isolation:** Separate build artifacts from source; never reuse artifacts across independent builds\n* **Access Control:** Limit file write permissions in CI environments to authenticated, trusted actors\n\n### Fixed Behaviour\n\nWhen a `.coverage` file is detected for a PHPT test prior to execution, PHPUnit will emit a clear error message identifying the anomalous state. This ensures:\n\n* **Visibility:** The error appears prominently in CI/CD output and test logs\n* **Investigation:** Operations teams can investigate the root cause (potential tampering, environment contamination)\n* **Fail-Fast Semantics:** Test execution stops rather than proceeding with an unexpected state\n\n### Recommendation\n\n**Update to the patched version immediately** if a project runs PHPT tests using PHPUnit with coverage instrumentation in any CI/CD environment that executes code from external contributors. Additionally, audit the project's CI/CD configuration to ensure:\n\n* Pull requests from forks or untrusted sources execute in isolated environments\n* Branch protection rules require human review before code execution\n* CI/CD runners are ephemeral and discarded after each build\n* Build artifacts are not reused across independent runs without validation","published":"2026-01-27T21:35:54.292Z","modified":"2026-10-28T02:30:40.510496335Z","cvss":{"score":7.8,"severity":"HIGH","vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"phpunit/phpunit","fixedVersion":"8.5.52"},{"ecosystem":"Packagist","name":"phpunit/phpunit","fixedVersion":"9.6.33"},{"ecosystem":"Packagist","name":"phpunit/phpunit","fixedVersion":"10.5.62"},{"ecosystem":"Packagist","name":"phpunit/phpunit","fixedVersion":"11.5.50"},{"ecosystem":"Packagist","name":"phpunit/phpunit","fixedVersion":"12.5.8"}],"fix":{"url":"https://github.com/sebastianbergmann/phpunit/commit/3141742e00620e2968d3d2e732d320de76685fda","label":"sebastianbergmann/phpunit@3141742"},"references":[{"type":"WEB","url":"https://github.com/sebastianbergmann/phpunit/releases/tag/10.5.63"},{"type":"WEB","url":"https://github.com/sebastianbergmann/phpunit/releases/tag/11.5.50"},{"type":"WEB","url":"https://github.com/sebastianbergmann/phpunit/releases/tag/12.5.8"},{"type":"WEB","url":"https://github.com/sebastianbergmann/phpunit/releases/tag/8.5.52"},{"type":"WEB","url":"https://github.com/sebastianbergmann/phpunit/releases/tag/9.6.33"},{"type":"WEB","url":"https://lists.debian.org/debian-lts-announce/2026/02/msg00009.html"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/24xxx/CVE-2026-24765.json"},{"type":"ADVISORY","url":"https://github.com/sebastianbergmann/phpunit/security/advisories/GHSA-vvj3-c3rp-c85p"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-24765"},{"type":"FIX","url":"https://github.com/sebastianbergmann/phpunit/commit/3141742e00620e2968d3d2e732d320de76685fda"},{"type":"WEB","url":"https://github.com/sebastianbergmann/phpunit/commit/613d142f5a8471ca71623ce5ca2795f79248329e"},{"type":"WEB","url":"https://github.com/FriendsOfPHP/security-advisories/blob/master/phpunit/phpunit/CVE-2026-24765.yaml"},{"type":"PACKAGE","url":"https://github.com/sebastianbergmann/phpunit"},{"type":"WEB","url":"https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-04-Poisoned-Pipeline-Execution"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:40.510496335Z"}}