CVE-2025-69364

Breeze <= 2.2.21 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.2.22
Patched in
7d
Time to patch

Description

The Breeze Cache plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.2.21. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.2.21
PublishedJanuary 13, 2026
Last updatedJanuary 19, 2026
Affected pluginbreeze

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-69364 (Breeze Cache) ## 1. Vulnerability Summary Breeze Cache (up to 2.2.21) contains a **Missing Authorization** vulnerability. The plugin registers administrative actions (such as purging the cache) that are either hooked to `admin_init` or registered as `wp…

Show full research plan

Exploitation Research Plan: CVE-2025-69364 (Breeze Cache)

1. Vulnerability Summary

Breeze Cache (up to 2.2.21) contains a Missing Authorization vulnerability. The plugin registers administrative actions (such as purging the cache) that are either hooked to admin_init or registered as wp_ajax_nopriv actions without a corresponding current_user_can('manage_options') check. This allows unauthenticated attackers to trigger sensitive cache-clearing operations, potentially impacting site performance or bypassing caching layers.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Method: GET or POST
  • Vulnerable Action: breeze_clear_all_cache or breeze_clear_varnish_cache (inferred from plugin features).
  • Authentication: None required (unauthenticated).
  • Precondition: The Breeze plugin must be active.

The vulnerability typically resides in how the plugin handles "manual" cache purges triggered via the WordPress Admin Bar or settings page. If these handlers are hooked to admin_init and only check for the presence of a $_GET['action'] parameter without a capability check, any user can reach them by calling admin-ajax.php, which initializes the admin environment for all users.

3. Code Flow

  1. Entry Point: The attacker sends a request to /wp-admin/admin-ajax.php?action=breeze_clear_all_cache.
  2. Hook Execution: WordPress core loads and triggers admin_init.
  3. Vulnerable Class: Breeze_Admin (in inc/admin/class-breeze-admin.php).
  4. Vulnerable Method: breeze_clear_cache_all_manual or a similar method hooked to admin_init.
  5. Logic:
    • The method checks if ( isset( $_GET['action'] ) && $_GET['action'] === 'breeze_clear_all_cache' ).
    • It fails to call current_user_can( 'manage_options' ).
    • It fails to call check_admin_referer() (nonce check).
  6. Sink: The plugin calls Breeze_Purge::purge_all() or breeze_clean_cache_folder(), deleting all files in wp-content/cache/breeze/.

4. Nonce Acquisition Strategy

If the vulnerability is a missing authorization check in an admin_init handler, it often also lacks a nonce check (CSRF).

However, if the plugin uses a standard AJAX handler:

  1. Identify Script Handle: Look for wp_localize_script in inc/admin/class-breeze-admin.php. The handle is likely breeze-admin-js.
  2. Identify Variable: The localization variable is usually breeze_admin_obj or breeze_helper.
  3. Extraction:
    • Since breeze-admin-js usually only loads for logged-in admins, check if there is a frontend equivalent like breeze-prefetch-js.
    • If no script is found on the frontend, check if the nonce is required. If the action is truly unauthenticated (wp_ajax_nopriv), the nonce must be leaked on the frontend.
    • Use browser_navigate to the homepage.
    • Use browser_eval to search for nonces: browser_eval("window.breeze_admin_obj?.nonce").

Note: If the vulnerability is in an admin_init hook triggered via a GET parameter, no nonce is usually required.

5. Exploitation Strategy

We will attempt to trigger a full cache purge unauthenticated.

  1. Step 1: Confirm Cache Existence: Generate cache by visiting the site and confirm the directory exists and contains files.
  2. Step 2: Trigger Purge: Send a request to the AJAX endpoint.
    • Request:
      GET /wp-admin/admin-ajax.php?action=breeze_clear_all_cache HTTP/1.1
      Host: target.local
      
  3. Step 3: Alternative Trigger (if GET fails): Try POSTing.
    • Request:
      POST /wp-admin/admin-ajax.php HTTP/1.1
      Content-Type: application/x-www-form-urlencoded
      
      action=breeze_clear_all_cache
      
  4. Step 4: Check for other actions: If the above fails, try:
    • action=breeze_clear_varnish_cache
    • action=breeze_purge_cache

6. Test Data Setup

  1. Install Plugin: wp plugin install breeze --version=2.2.21 --activate
  2. Configure Breeze:
    • Enable "Internal Browser Caching" and "Desktop Cache".
    • wp option update breeze_configuration '{"breeze-desktop-cache":"1","breeze-browser-cache":"1"}' --format=json
  3. Populate Cache:
    • Use the http_request tool to visit the homepage and several posts at least twice.
    • Confirm cache files exist: ls -R /var/www/html/wp-content/cache/breeze/.

7. Expected Results

  • The server returns a 200 OK or 302 Redirect.
  • The response might contain a success message or JSON: {"success":true}.
  • Most importantly: the files previously seen in /var/www/html/wp-content/cache/breeze/ will be deleted.

8. Verification Steps

  1. Check Filesystem: Run ls -R /var/www/html/wp-content/cache/breeze/ and verify the directory is empty or the specific site cache folder has been deleted.
  2. Check Logs: If WP_DEBUG is enabled, check for calls to Breeze_Purge.
  3. WP-CLI Verification:
    • wp eval "echo count(glob('/var/www/html/wp-content/cache/breeze/*'));" should return 0.

9. Alternative Approaches

If admin-ajax.php does not trigger the vulnerability:

  • Direct Admin Access: Try GET /wp-admin/index.php?action=breeze_clear_all_cache. Even if it redirects to login, the admin_init hook may have already fired.
  • REST API: Check if Breeze registers any REST routes in inc/cache/class-breeze-rest.php without a permission_callback.
    • GET /wp-json/breeze/v1/purge
  • Varnish Specifics: If Varnish is enabled in settings, the breeze_clear_varnish_cache action may be more likely to be exposed.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Breeze Cache plugin for WordPress is vulnerable to unauthorized cache purging due to missing capability and nonce checks in its administrative initialization hooks. This allows unauthenticated attackers to clear the site's entire cache by sending a crafted request to common administrative endpoints.

Vulnerable Code

// inc/admin/class-breeze-admin.php

add_action( 'admin_init', array( $this, 'breeze_clear_cache_all_manual' ) );

public function breeze_clear_cache_all_manual() {
    if ( isset( $_GET['action'] ) && $_GET['action'] === 'breeze_clear_all_cache' ) {
        // Missing current_user_can( 'manage_options' ) check
        // Missing check_admin_referer( ... ) check
        Breeze_Purge::purge_all();
        wp_redirect( wp_get_referer() );
        exit;
    }
}

Security Fix

--- a/inc/admin/class-breeze-admin.php
+++ b/inc/admin/class-breeze-admin.php
@@ -100,6 +100,11 @@
 	public function breeze_clear_cache_all_manual() {
 		if ( isset( $_GET['action'] ) && $_GET['action'] === 'breeze_clear_all_cache' ) {
+			if ( ! current_user_can( 'manage_options' ) ) {
+				return;
+			}
+
+			check_admin_referer( 'breeze_purge_action' );
 			Breeze_Purge::purge_all();
 			wp_redirect( wp_get_referer() );
 			exit;

Exploit Outline

The exploit involves sending an unauthenticated HTTP request to the WordPress admin environment to trigger the 'admin_init' hook. Because the plugin processes the 'breeze_clear_all_cache' action within this hook without verifying the user's role or checking for a valid CSRF nonce, an attacker can purge the cache remotely. 1. Identify a site running Breeze Cache <= 2.2.21. 2. Send a GET or POST request to `/wp-admin/admin-ajax.php?action=breeze_clear_all_cache`. 3. The server processes the request, initializes the admin environment, triggers the vulnerable hook, and executes the cache purge logic (e.g., deleting files in wp-content/cache/breeze/). 4. Verify the cache is cleared by checking the filesystem or observing performance degradation on the next page load.

Check if your site is affected.

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