CVE-2025-48883 Overview
CVE-2025-48883 affects Chrome PHP, a library that lets developers control Chrome or Chromium in headless mode from PHP. Versions prior to 1.14.0 fail to properly encode CSS Selector expressions before passing them to the browser context. Attackers can leverage this gap to inject JavaScript through selector strings, resulting in cross-site scripting (XSS) [CWE-79]. The maintainers patched the flaw in version 1.14.0 by JSON-encoding selector expressions before interpolation into document.querySelectorAll calls.
Critical Impact
Unencoded CSS selectors flow into JavaScript execution inside the headless browser, allowing attacker-controlled input to execute arbitrary script in the browsing context.
Affected Products
- Chrome PHP (chrome-php/chrome) versions prior to 1.14.0
- Applications using CssSelector with untrusted input in headless automation
- PHP-based scraping and testing pipelines that pass user input into selectors
Discovery Timeline
- 2025-05-30 - CVE-2025-48883 published to NVD
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2025-48883
Vulnerability Analysis
Chrome PHP builds JavaScript expressions as strings and evaluates them inside the controlled Chrome instance. The CssSelector class inserted user-supplied selector expressions directly into string templates such as document.querySelectorAll("..."). When the selector contained characters like double quotes, backslashes, or newlines, the resulting JavaScript broke out of the string literal. Attackers who influence the selector value can append arbitrary JavaScript statements that execute in the browser context driven by the automation script.
The issue is classified as Improper Neutralization of Input During Web Page Generation [CWE-79]. Exploitation requires that an application forward attacker-controlled data into a Chrome PHP selector call, and it depends on user or automation interaction to trigger the browser action.
Root Cause
The root cause is missing output encoding in src/Dom/Selector/CssSelector.php. The constructor stored the raw expression and used sprintf to concatenate it into JavaScript source. Because the input was never escaped for a JavaScript string context, any quote or control character in the selector terminated the literal and enabled code injection.
Attack Vector
An attacker supplies a crafted selector string, for example through a form field, API parameter, or URL that a PHP application forwards to CssSelector. When Chrome PHP builds the JavaScript expression and the headless Chrome runtime evaluates it, the injected payload executes with the privileges of the automation session, including access to page content and cookies handled by that session.
// Patch from src/Dom/Selector/CssSelector.php (v1.14.0)
final class CssSelector implements Selector
{
/** @var string */
- private $expression;
+ private $expressionEncoded;
public function __construct(string $expression)
{
- $this->expression = $expression;
+ $this->expressionEncoded = \json_encode(
+ $expression,
+ \JSON_UNESCAPED_SLASHES
+ | \JSON_UNESCAPED_UNICODE
+ | \JSON_THROW_ON_ERROR
+ );
}
public function expressionCount(): string
{
- return \sprintf('document.querySelectorAll("%s").length', $this->expression);
+ return \sprintf(
+ 'document.querySelectorAll(%s).length',
+ $this->expressionEncoded
+ );
}
public function expressionFindOne(int $position): string
{
- return \sprintf('document.querySelectorAll("%s")[%d]', $this->expression, $position - 1);
+ return \sprintf(
Source: chrome-php/chrome commit 34b2b8d. The fix replaces raw string interpolation with json_encode, which escapes quotes, backslashes, and control characters before the value reaches the JavaScript runtime.
Detection Methods for CVE-2025-48883
Indicators of Compromise
- Unexpected JavaScript payloads or quote characters (", \\, \n) appearing in application logs where CSS selectors are recorded
- Headless Chrome sessions issuing outbound network requests to domains unrelated to the target scraping or testing workflow
- Errors from document.querySelectorAll referencing unexpected syntax in Chrome PHP debug output
Detection Strategies
- Perform a dependency inventory to identify PHP projects pinning chrome-php/chrome below version 1.14.0 through composer.lock review
- Audit application code for calls that pass untrusted input into CssSelector or related selector classes without validation
- Add static analysis rules that flag string concatenation of external input with Chrome PHP selector APIs
Monitoring Recommendations
- Log the selector expressions submitted to headless automation and alert on non-alphanumeric bursts that suggest injection attempts
- Monitor headless Chrome process telemetry for outbound connections, DOM exfiltration patterns, or unexpected child processes
- Track upstream releases of chrome-php/chrome through the GitHub Security Advisory GHSA-3432-fmrf-7vmh
How to Mitigate CVE-2025-48883
Immediate Actions Required
- Upgrade chrome-php/chrome to version 1.14.0 or later using composer update chrome-php/chrome
- Review all call sites that construct CssSelector instances from user or third-party input
- Restrict the network egress and filesystem privileges of processes running headless Chrome to contain any residual injection
Patch Information
The fix is delivered in Chrome PHP 1.14.0 through Pull Request #691 and applied in commit 34b2b8d. The patched CssSelector class encodes expressions with json_encode using JSON_UNESCAPED_SLASHES, JSON_UNESCAPED_UNICODE, and JSON_THROW_ON_ERROR flags before embedding them in JavaScript. Full details are documented in GitHub Security Advisory GHSA-3432-fmrf-7vmh.
Workarounds
- If upgrading is not possible, apply manual encoding to selector strings before passing them to Chrome PHP, mirroring the json_encode approach used in the official patch
- Enforce an allow-list of selector patterns and reject characters such as ", \\, and newlines from user input
- Isolate headless Chrome workers in sandboxed containers with restricted outbound network access to limit XSS impact
# Upgrade Chrome PHP to the patched release
composer require chrome-php/chrome:^1.14.0
composer update chrome-php/chrome
# Verify the installed version
composer show chrome-php/chrome | grep versions
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

