CVE-2025-14384

All in One SEO – Powerful SEO Plugin to Boost SEO Rankings & Increase Traffic <= 4.9.2 - Missing Authorization to Authenticated (Contributor+) AI Access Token and Credit Disclosure

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
4.9.3
Patched in
1d
Time to patch

Description

The All in One SEO – Powerful SEO Plugin to Boost SEO Rankings & Increase Traffic plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the `/aioseo/v1/ai/credits` REST route in all versions up to, and including, 4.9.2. This makes it possible for authenticated attackers, with Contributor-level access and above, to disclose the global AI access token.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.9.2
PublishedJanuary 15, 2026
Last updatedJanuary 16, 2026
Affected pluginall-in-one-seo-pack

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to verify and exploit **CVE-2025-14384**, a missing authorization vulnerability in the **All in One SEO (AIOSEO)** plugin. --- ### 1. Vulnerability Summary * **Vulnerability:** Missing Authorization to Authenticated (Contributor+) AI Access Token and Credit …

Show full research plan

This research plan outlines the steps to verify and exploit CVE-2025-14384, a missing authorization vulnerability in the All in One SEO (AIOSEO) plugin.


1. Vulnerability Summary

  • Vulnerability: Missing Authorization to Authenticated (Contributor+) AI Access Token and Credit Disclosure.
  • ID: CVE-2025-14384
  • Plugin Slug: all-in-one-seo-pack
  • Affected Versions: <= 4.9.2
  • Patched Version: 4.9.3
  • Vulnerable Component: REST API route /aioseo/v1/ai/credits.
  • Nature of Issue: The REST route registration for the AI credits endpoint fails to implement a proper permission_callback that restricts access to administrators or users with aioseo_manage_seo capabilities. Instead, it allows any authenticated user with at least Contributor-level access to query the endpoint and retrieve the global AI access token and usage details.

2. Attack Vector Analysis

  • Endpoint: GET /wp-json/aioseo/v1/ai/credits
  • Authentication Required: Authenticated, minimum level Contributor.
  • Payload Parameter: None (Direct GET request).
  • Preconditions:
    1. The AIOSEO plugin must be installed and active (v4.9.2 or below).
    2. An attacker must have valid credentials for a user with at least the Contributor role.
    3. A valid REST API nonce (wp_rest) is required for the request.

3. Code Flow (Inferred)

  1. Route Registration: The plugin registers REST routes during the rest_api_init hook. This likely occurs in app/Common/RestApi/RestApi.php or a dedicated AI API class such as app/Common/Api/Ai.php.
  2. Missing Check: The route /aioseo/v1/ai/credits is registered with a permission_callback. In the vulnerable version, this callback likely checks for is_user_logged_in() or a low-level capability like edit_posts (granted to Contributors) rather than AIOSEO-specific management capabilities.
  3. Data Retrieval: The controller method associated with this route (e.g., getCredits) calls an internal AIOSEO helper to retrieve the AI service configuration.
  4. Response: The helper returns an array/object containing the access_token and credit balances, which the REST API then serializes into a JSON response.

4. Nonce Acquisition Strategy

To make an authenticated request to the WordPress REST API, a wp_rest nonce is required.

  1. Identification: AIOSEO heavily uses localized JavaScript to pass data to its Vue/React frontend. The wp_rest nonce is typically included in a global object.
  2. Verification Page: The AIOSEO "General Settings" or "Post Editor" pages are likely to contain these scripts.
  3. Extraction Steps:
    • Log in as a Contributor.
    • Navigate to the WordPress Dashboard (any page, as AIOSEO often enqueues assets on all admin pages for its top-bar menu).
    • Use browser_eval to extract the nonce from the aioseo or aioseoData global variable.
  4. JavaScript Path:
    • browser_eval("window.aioseo?.nonce")
    • OR browser_eval("window.aioseoData?.nonce")
    • Alternatively, look for the standard WordPress wpApiSettings if enqueued: browser_eval("window.wpApiSettings?.nonce").

5. Exploitation Strategy

  1. Environment Setup: Create a user with the Contributor role.
  2. Session Initiation: Log in to the WordPress dashboard as the Contributor.
  3. Nonce Extraction: Execute the JavaScript extraction mentioned in Section 4 to obtain the _wpnonce.
  4. Target Request: Use the http_request tool to perform a GET request to the vulnerable endpoint.

HTTP Request Details:

  • Method: GET
  • URL: http://[target-site]/wp-json/aioseo/v1/ai/credits
  • Headers:
    • X-WP-Nonce: [EXTRACTED_NONCE]
    • Content-Type: application/json
    • Cookie: [CONTRIBUTOR_SESSION_COOKIES]

6. Test Data Setup

  1. Plugin Installation: Install All in One SEO version 4.9.2.
  2. Contributor Account:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  3. AI Configuration (Optional): To ensure a token is returned, the researcher may need to simulate a connection to AIOSEO AI services, although the code path should attempt to return whatever is stored in the options table (e.g., aioseo_options).

7. Expected Results

A successful exploit will return a 200 OK response with a JSON body similar to:

{
    "credits": {
        "total": 100,
        "used": 10,
        "remaining": 90
    },
    "token": "sk_aioseo_abcdef1234567890...",
    "success": true
}

Wait for the token or access_token field in the response.

8. Verification Steps

  1. Check Capability Logic: Using WP-CLI, verify which capability is required to manage AIOSEO normally (usually aioseo_manage_seo). Confirm that the contributor role DOES NOT have this capability:
    wp capability list contributor | grep aioseo
    
  2. Database Correlation: Verify that the token returned in the HTTP response matches the one stored in the database:
    wp option get aioseo_options --format=json | jq '.. | .access_token?'
    

9. Alternative Approaches

  • Route Variant: If /aioseo/v1/ai/credits does not yield the token, check related endpoints in the same namespace such as /aioseo/v1/ai/config.
  • Frontend Check: If the AI token is loaded into the aioseo JS object for Contributors on the post editing page, the token could be disclosed directly via browser_eval without a REST request, though the CVE specifically cites the REST route.
  • Direct Option Access: If the REST API endpoint allows setting values (not just disclosure), check for a corresponding POST or PUT method that might allow for unauthorized modification of AI settings.
Research Findings
Static analysis — not yet PoC-verified

Summary

The All in One SEO (AIOSEO) plugin for WordPress (<= 4.9.2) lacks proper authorization checks on its AI credits REST API endpoint. Authenticated users with Contributor-level permissions or higher can access the `/aioseo/v1/ai/credits` route to disclose the global AI access token and credit usage information.

Vulnerable Code

// app/Common/Api/Ai.php

register_rest_route( 'aioseo/v1', '/ai/credits', [
    'methods'             => 'GET',
    'callback'            => [ $this, 'getCredits' ],
    'permission_callback' => function() {
        // Vulnerable: Allows any user with 'edit_posts' (Contributors and above) to access the endpoint
        return current_user_can( 'edit_posts' );
    }
] );

---

// Inferred controller logic returning sensitive data
public function getCredits( $request ) {
    $options = aioseo()->options->all();
    return new WP_REST_Response( [
        'success' => true,
        'credits' => $this->aiService->getCredits(),
        'token'   => $options['ai']['access_token'] ?? null
    ], 200 );
}

Security Fix

--- a/app/Common/Api/Ai.php
+++ b/app/Common/Api/Ai.php
@@ -10,7 +10,7 @@
             'methods'             => 'GET',
             'callback'            => [ $this, 'getCredits' ],
             'permission_callback' => function() {
-                return current_user_can( 'edit_posts' );
+                return current_user_can( 'aioseo_manage_seo' );
             }
         ] );

Exploit Outline

To exploit this vulnerability, an attacker needs a low-privileged account (Contributor+) and a valid REST API nonce. 1. Authenticate as a Contributor user and access the WordPress admin dashboard. 2. Locate the REST API nonce from the page source, typically found in localized JavaScript objects such as `window.aioseo.nonce` or `window.wpApiSettings.nonce`. 3. Send a GET request to `/wp-json/aioseo/v1/ai/credits` including the extracted nonce in the `X-WP-Nonce` header. 4. The server response will contain the sensitive `access_token` and credit details for the AIOSEO AI service in the JSON body, which the attacker can then use for unauthorized AI requests.

Check if your site is affected.

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