Post

CVE-2026-104751: Rank Math SEO Unauthenticated SEO Analyzer Results Deletion

Source-level analysis and local runtime validation of unauthenticated SEO Analyzer cache deletion in Rank Math SEO versions before 1.0.280.

CVE-2026-104751: Rank Math SEO Unauthenticated SEO Analyzer Results Deletion

CVE-2026-104751: Rank Math SEO Unauthenticated SEO Analyzer Results Deletion

Overview

CVE-2026-104751 is a missing authorization vulnerability in the Rank Math SEO WordPress plugin. In versions before 1.0.280, the SEO Analyzer could delete its stored analysis results and last-run timestamp as a side effect of module initialization, without authentication, capability validation, or a nonce check.

I validated the behavior on Rank Math SEO 1.0.279 in an isolated WordPress lab. An unauthenticated request reached the storage-clearing branch; the server responded with a Rank Math redirect, and two previously populated WordPress options disappeared. Negative controls showed no deletion when the triggering parameter was absent or different.

The data at issue is regenerable SEO Analyzer output, not posts, credentials, site configuration, or backup archives. No information disclosure, account compromise, remote code execution, or site-wide denial of service was demonstrated.

Summary

PropertyValue
CVECVE-2026-104751
ProductRank Math SEO (seo-by-rank-math)
Affected versions (WPScan)< 1.0.280
Validated version1.0.279
Fixed version (WPScan)1.0.280
WeaknessCWE-862 — Missing Authorization
ClassificationNo Authorisation / Broken Access Control
SeverityMedium
CVSS v3.15.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N)
Authentication requiredNone
Researcher and submitterDuy Tran (MrDarkRoot)
WPVDB IDb68d607d-aad8-46ad-a522-5eaeea738d8c
Public disclosure (WPScan)October 12, 2026

Expected Behavior

Only an authorized administrator should be able to clear stored SEO Analyzer results. A destructive operation should validate the user’s relevant capability and the authenticity of the action before mutating WordPress options. Unauthenticated AJAX initialization should not grant permission to delete administrator-generated analysis state.

Actual Behavior

The SEO Analyzer constructor invokes maybe_clear_storage(). In the vulnerable implementation, this method checks a request parameter and immediately deletes stored SEO results and their timestamp, with no capability or nonce verification before the destructive calls.

1. Untrusted parameter controls the deletion sink

The relevant code from includes/modules/seo-analysis/class-seo-analyzer.php in the examined release:

1
2
3
4
5
6
7
8
private function maybe_clear_storage() {
    if ( '1' === Param::request( 'clear_results' ) ) {
        delete_option( 'rank_math_seo_analysis_results' );
        delete_option( 'rank_math_seo_analysis_date' );
        Helper::redirect( Security::remove_query_arg_raw( 'clear_results' ) );
        exit;
    }
}

The value of clear_results is attacker-controlled. There is no current_user_can() or nonce check before delete_option(). The redirect is a consequence of the branch, not an authorization defense.

2. The deletion runs during construction

1
2
3
4
5
6
7
8
public function __construct() {
    $this->analyse_url = home_url();
    $this->action( 'init', 'set_url' );
    $this->maybe_clear_storage();

    $this->ajax( 'analyze', 'analyze_me' );
    $this->ajax( 'enable_auto_update', 'enable_auto_update' );
}

This places request-driven database mutation in object initialization, rather than in a dedicated privileged action handler.

3. Unauthenticated AJAX requests instantiate the analyzer

In includes/modules/seo-analysis/class-admin.php, the module constructs the analyzer when the AJAX execution flag is set or its administration page is current:

1
2
3
4
if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || $this->page->is_current_page() ) {
    include_once 'seo-analysis-tests.php';
    $this->analyzer = new SEO_Analyzer();
}

WordPress’s wp-admin/admin-ajax.php defines the AJAX/admin context before loading WordPress. The Rank Math module-loading path treated that context as sufficient to instantiate the SEO Analysis administration component, even when the visitor was logged out.

Thus, a request could reach the constructor and maybe_clear_storage() before any user-level authorization check.

4. Regeneration has an authorization boundary

By contrast, the analyzer’s analyze_me() action includes:

1
2
check_ajax_referer( 'rank-math-ajax-nonce', 'security' );
$this->has_cap_ajax( 'site_analysis' );

Generating the results was nonce- and capability-gated, but deleting the same results was not. This asymmetric design is the core trust-boundary failure.

Required Conditions / Attack Preconditions

The SEO Analysis module must be active (enabled by default in the examined installation), and results must already have been generated for there to be any data to remove. An attacker does not require WordPress credentials, cookies, API tokens, or special headers.

Trust-Boundary Analysis

The violated invariant was:

1
2
External HTTP input
    must not authorize destructive administrative state changes

The vulnerable flow was:

1
2
3
4
5
Unauthenticated admin-ajax bootstrap
    -> Rank Math administrative module initialization
    -> new SEO_Analyzer()
    -> maybe_clear_storage()
    -> delete_option() twice

is_admin() and DOING_AJAX describe WordPress execution context; neither proves an authenticated or authorized administrator.

Technical Validation

The original report documented an isolated environment:

ComponentTested version
WordPress7.1.2 (reported lab configuration)
Rank Math SEO1.0.279
PHP8.2.34
MySQL8.0.46
AuthenticationNone

Baseline

The options table contained:

1
2
rank_math_seo_analysis_results    10290 bytes
rank_math_seo_analysis_date          10 bytes

Positive result

After an unauthenticated trigger request, the application returned:

1
2
3
HTTP/1.1 302 Found
X-Redirect-By: Rank Math
Location: /wp-admin/admin-ajax.php

Database inspection then showed neither option existed. The two options were still absent when checked 30 seconds later. The redirect alone would not prove deletion; the before-and-after database inspection did.

Negative controls

Requests to the same AJAX entry point with the triggering parameter absent or set to a non-triggering value returned HTTP 400. In these controls, both options remained present and unchanged.

The differential behavior connects the deletion to the specific unprotected branch rather than ordinary AJAX bootstrap.

Proof of Concept

A single unauthenticated GET request was sufficient to trigger the deletion in the local lab. The original report preserved the precise request and database checks.

This public post intentionally focuses on the verified code path and observed effects; it does not reproduce the complete operational trigger request. The issue is publicly disclosed and patched in 1.0.280 according to WPScan.

Impact

Observed: An unauthenticated actor deleted the stored SEO analysis results and date. The change persisted until an authorized administrator regenerated the analysis.

Potential: Repeated requests could continually clear regenerated audit state, disrupting the usefulness of retained SEO Analyzer results.

Limits: These options are regenerable analysis data. The test did not establish broader WordPress content deletion, privilege escalation, information disclosure, remote code execution, or general service unavailability. WPScan assigns a 5.3 Medium CVSS score.

Remediation

WPScan lists the issue as fixed in Rank Math SEO 1.0.280. Administrators should update to version 1.0.280 or newer.

Secure implementation principles include:

  1. Check the rank_math_site_analysis capability and verify a nonce before any storage deletion.
  2. Move destructive logic from constructors to explicit, authorized action handlers.
  3. Do not confuse an AJAX/admin execution context with an authenticated administrator.
  4. Regression-test the missing, non-triggering, and unauthenticated request cases against the stored options.

Disclosure Timeline

DateEvent
Date not publicly specifiedLocal source review and runtime validation on 1.0.279
October 12, 2026Public WPScan disclosure of CVE-2026-104751
October 13, 2026Technical write-up updated with confirmed CVE, version range, severity and patch metadata

Research Credit

Original researcher and submitter: Duy Tran (MrDarkRoot).

WPScan identifies the finding as verified. The source-level analysis and lab results here are based on my original report; advisory metadata such as affected versions, CVE identifier, fixed version and CVSS score comes from the public WPScan record.

References

Responsible Disclosure Notice

This research was conducted in an isolated local test environment and published following public advisory disclosure. Do not test third-party websites without authorization. Update Rank Math SEO to 1.0.280 or later to address the reported issue.

This post is licensed under CC BY 4.0 by the author.
Support my research