CVE-2026-12408

Slim SEO <= 4.9.8 - Authenticated (Contributor+) Insufficient Authorization to Private Content Disclosure via 'object.ID' Parameter

mediumExposure of Sensitive Information to an Unauthorized Actor
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
4.9.9
Patched in
1d
Time to patch

Description

The Slim SEO – A Fast & Automated SEO Plugin For WordPress plugin for WordPress is vulnerable to Unauthorized Private Content Disclosure in all versions up to, and including, 4.9.8 via the `/wp-json/slim-seo/meta-tags/ai` REST API endpoint. This is due to the endpoint's `permission_callback` performing only a top-level `edit_posts` capability check without verifying that the requesting user has read access to the specific post supplied via the `object.ID` parameter, allowing the `generate` function to pass the attacker-controlled post ID to `Data::get_post_content()`, which calls `get_post()` regardless of post status or ownership. This makes it possible for authenticated attackers with Contributor-level access and above to retrieve AI-generated summaries of the raw `post_content` of arbitrary posts they are not authorized to view — including private posts, drafts, pending, future, and password-protected content authored by other users — with the substance of the protected content disclosed via the HTTP response.

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.8
PublishedJune 30, 2026
Last updatedJuly 1, 2026
Affected pluginslim-seo

What Changed in the Fix

Changes introduced in v4.9.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-12408 - Slim SEO Private Content Disclosure ## 1. Vulnerability Summary The **Slim SEO** plugin (versions <= 4.9.8) contains an authorization bypass vulnerability in its AI-powered meta-tag generation REST API endpoint. The endpoint `/wp-json/slim-seo/meta-tags/ai` is inte…

Show full research plan

Research Plan: CVE-2026-12408 - Slim SEO Private Content Disclosure

1. Vulnerability Summary

The Slim SEO plugin (versions <= 4.9.8) contains an authorization bypass vulnerability in its AI-powered meta-tag generation REST API endpoint. The endpoint /wp-json/slim-seo/meta-tags/ai is intended to allow users with the edit_posts capability (Contributor level and above) to generate SEO summaries.

However, the permission_callback for this route only verifies the user's top-level capability (edit_posts) and fails to check if the user has permission to read the specific post identified by the object.ID parameter. Consequently, the generate function passes this ID to Data::get_post_content(), which retrieves post data via get_post() without regard for post status (private, draft, password-protected) or ownership. This allows an attacker to obtain AI-generated summaries of sensitive content they are not authorized to view.

2. Attack Vector Analysis

  • REST API Endpoint: /wp-json/slim-seo/meta-tags/ai
  • Method: POST (Typically used for generation/processing endpoints in Slim SEO)
  • Vulnerable Parameter: object.ID (likely passed as part of a JSON payload)
  • Required Authentication: Authenticated user with edit_posts capability (Contributor level).
  • Impact: Disclosure of sensitive information from private, draft, pending, or password-protected posts and pages across the entire WordPress site.

3. Code Flow

  1. Request Entry: An authenticated Contributor sends a request to /wp-json/slim-seo/meta-tags/ai.
  2. Authorization Check: The REST API router executes the permission_callback. It checks current_user_can( 'edit_posts' ). This returns true for Contributors.
  3. Controller Execution: The request proceeds to the generate function (likely within an AI-related controller class in src/).
  4. Parameter Handling: The controller extracts the object.ID from the request object.
  5. Data Retrieval: The controller calls SlimSEO\Data::get_post_content( $post_id ) (inferred class/method).
  6. Information Sink: Inside get_post_content(), the plugin calls get_post( $post_id ). WordPress's get_post() retrieves the post object regardless of the current user's read permissions.
  7. AI Processing: The raw post_content is sent to the configured AI provider (OpenAI/Anthropic) to generate a summary/meta tag.
  8. Response: The AI-generated summary of the private content is returned in the HTTP response to the Contributor.

4. Nonce Acquisition Strategy

The endpoint is a WordPress REST API route. Standard WordPress REST API security requires the X-WP-Nonce header for authenticated requests.

  1. User Role: Contributor.
  2. Strategy: Log in as the Contributor and navigate to the WordPress Dashboard (/wp-admin/). The REST API nonce (wp_rest) is globally available in the wpApiSettings JavaScript object on most admin pages.
  3. Execution:
    • Use browser_navigate to go to /wp-admin/.
    • Use browser_eval to extract the nonce:
      window.wpApiSettings.nonce
      
    • This nonce is valid for the wp_rest action, which authorizes requests to /wp-json/.

5. Exploitation Strategy

Step 1: Discover Target Post ID

Identify the ID of a private post authored by the Administrator. This can often be done by brute-forcing IDs or viewing the sitemap if IDs are leaked there (though private posts usually aren't). For the PoC, we will create a post and note its ID.

Step 2: The Attack Request

As a Contributor, send the following request:

  • URL: http://localhost:8080/wp-json/slim-seo/meta-tags/ai
  • Method: POST
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Body:
    {
      "object": {
        "ID": [PRIVATE_POST_ID]
      },
      "type": "description"
    }
    
    (Note: The type parameter is inferred from the plugin's "Meta Tags" functionality which generates titles and descriptions).

Step 3: Analyze Response

A successful exploit will return a 200 OK response with a JSON body containing a "content" or "result" field. This field will contain a summary of the private post's content.

6. Test Data Setup

  1. Create Administrator Post:
    wp post create --post_type=post --post_title="Top Secret Strategy" --post_content="The password to the vault is 'Blue-Monkey-42'. We launch the product on Friday at midnight." --post_status=private --post_author=1
    
    Note the resulting ID (e.g., 123).
  2. Create Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  3. Configure Slim SEO AI (Optional/Mock):
    The AI feature might require an API key to be set in Slim SEO settings. If the environment does not have internet access, the researcher may need to mock the AI response or check if the plugin fails after retrieving the content but before calling the API (though the vulnerability usually results in the data being sent to the AI service).

7. Expected Results

  • Request: Contributor sends POST to /wp-json/slim-seo/meta-tags/ai with object.ID=123.
  • Authorization: permission_callback returns true.
  • Response: JSON response containing a summary like: "Generated description: Strategy involving vault password 'Blue-Monkey-42' and a Friday launch."
  • Security Failure: The Contributor has successfully retrieved the "gist" of a private post owned by the Admin.

8. Verification Steps

  1. Confirm Post Status: Use WP-CLI to ensure the post is indeed private.
    wp post get [ID] --field=post_status
    
  2. Verify User Permissions: Ensure the Contributor cannot view the post normally.
    • Try to access /?p=[ID] as the Contributor via browser_navigate.
    • Result should be a 404 or "Post not found".
  3. Confirm Data Leakage: Compare the content returned by the REST API with the original secret content.

9. Alternative Approaches

If the object.ID parameter is not nested:

  • Try {"ID": 123}
  • Try GET /wp-json/slim-seo/meta-tags/ai?object[ID]=123
  • Check for other AI endpoints mentioned in js/settings-ai.js: /slim-seo/bulk-ai/chunk or /slim-seo/ai/models for similar authorization flaws.

Note: The core vulnerability is the lack of if ( ! current_user_can( 'read_post', $post_id ) ) in the permission callback or the handler.

Check if your site is affected.

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