CVE-2025-14371

TaxoPress <= 3.41.0 - Missing Authorization to Authenticated (Contributor+) Arbitrary Post Tag Modification

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
3.42.0
Patched in
39d
Time to patch

Description

The Tag, Category, and Taxonomy Manager – AI Autotagger with OpenAI plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the taxopress_ai_add_post_term function in all versions up to, and including, 3.41.0. This makes it possible for authenticated attackers, with Contributor-level access and above, to add or remove taxonomy terms (tags, categories) on any post, including ones they do not own.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.41.0
PublishedJanuary 5, 2026
Last updatedFebruary 13, 2026
Affected pluginsimple-tags

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-14371 (TaxoPress AI Autotagger) ## 1. Vulnerability Summary The **TaxoPress** plugin (formerly Simple Tags) version 3.41.0 and below is vulnerable to unauthorized data modification. The function `taxopress_ai_add_post_term`, which is intended to allow the AI A…

Show full research plan

Exploitation Research Plan: CVE-2025-14371 (TaxoPress AI Autotagger)

1. Vulnerability Summary

The TaxoPress plugin (formerly Simple Tags) version 3.41.0 and below is vulnerable to unauthorized data modification. The function taxopress_ai_add_post_term, which is intended to allow the AI Autotagger feature to update post tags or categories, fails to implement a capability check (authorization).

While it typically enforces a nonce check (CSRF protection), the nonce is available to any user with dashboard access (Contributor and above). Because the code does not verify if the current user has the edit_post capability for the specific post_id provided in the request, a Contributor can add or remove terms from posts they do not own, including those published by Administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: taxopress_ai_add_post_term
  • HTTP Method: POST
  • Authentication: Required (Contributor or higher)
  • Vulnerable Parameter: post_id (used to target arbitrary posts)
  • Payload Parameters (Inferred):
    • post_id: Integer (The ID of the target post)
    • term: String (The term name to add)
    • taxonomy: String (The taxonomy slug, e.g., post_tag or category)
    • nonce: String (The security token)

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers the AJAX handler in its admin initialization:
    add_action('wp_ajax_taxopress_ai_add_post_term', 'taxopress_ai_add_post_term');
  2. Function Execution: taxopress_ai_add_post_term() is called.
  3. Nonce Verification: The function likely calls check_ajax_referer('taxopress_ai_nonce', 'nonce') or similar.
  4. Missing Authorization: The function proceeds to use wp_set_post_terms() or wp_add_object_terms() using the user-provided post_id without checking if the user is authorized to edit that specific post:
    // Vulnerable logic pattern
    $post_id = (int)$_POST['post_id'];
    $term    = sanitize_text_field($_POST['term']);
    $tax     = sanitize_text_field($_POST['taxonomy']);
    // NO CHECK: if (!current_user_can('edit_post', $post_id)) { wp_die(); }
    wp_set_post_terms($post_id, $term, $tax, true);
    

4. Nonce Acquisition Strategy

The AI Autotagger features are typically loaded in the WordPress Post Editor. Even a Contributor can create a "Draft" post to access the editor, which will load the necessary scripts and nonces.

  1. Identify Script Localization: The plugin likely uses wp_localize_script to pass a nonce to the editor. Based on common TaxoPress patterns, look for the taxopress_admin_params or taxopress_ai_autotagger object.
  2. Setup: Create a dummy post as the Contributor user.
  3. Navigation: Navigate to the editor for that dummy post: /wp-admin/post.php?post=[DUMMY_ID]&action=edit.
  4. Extraction: Use browser_eval to extract the nonce:
    • browser_eval("taxopress_admin_params.taxopress_ai_nonce") (inferred key)
    • Alternative: Search page source for nonce strings if the key differs.

5. Exploitation Strategy

  1. Login: Authenticate as a Contributor-level user.
  2. Acquire Nonce: Navigate to the editor for a post owned by the Contributor to grab the taxopress_ai_nonce.
  3. Identify Target: Determine the post_id of an Administrator's post (e.g., ID 1).
  4. Execute Attack: Send a POST request to admin-ajax.php.

Request Details:

  • URL: http://[target]/wp-admin/admin-ajax.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body:
    action=taxopress_ai_add_post_term&post_id=1&term=pwned&taxonomy=post_tag&nonce=[EXTRACTED_NONCE]
    

6. Test Data Setup

  1. Administrator Post: Create a post as admin.
    • wp post create --post_title="Admin Private News" --post_status=publish --post_author=1 (Note the ID, usually 1 or 4).
  2. Contributor User: Create a user with the contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  3. Contributor Post: Create a post for the contributor so they can access the editor.
    • wp post create --post_title="Contributor Post" --post_status=draft --post_author=[CONTRIBUTOR_ID]

7. Expected Results

  • The AJAX response should return a success code (e.g., {"success":true} or 1).
  • The Administrator's post (ID 1) will now have the tag "pwned" assigned to it, despite the Contributor having no permissions to modify that post.

8. Verification Steps

  1. Check Terms via CLI:
    • wp post term list 1 post_tag --fields=name
  2. Confirm Injection: Verify "pwned" appears in the output.
  3. Check Author: Verify the post is still owned by the Administrator.
    • wp post get 1 --field=post_author

9. Alternative Approaches

  • Taxonomy Variation: If post_tag is restricted, try category or any custom taxonomy registered on the site.
  • Bulk Action: If the function supports an array of terms, try injecting multiple terms.
  • Nonce Source: If the nonce is not in the Post Editor, check the TaxoPress settings pages in the dashboard (some are accessible to lower roles depending on plugin configuration).
  • Direct Parameter Guessing: If term doesn't work, try term_id or terms[]. (The vulnerability specifically mentions taxopress_ai_add_post_term, implying term addition).
Research Findings
Static analysis — not yet PoC-verified

Summary

The TaxoPress plugin for WordPress is vulnerable to unauthorized modification of taxonomy data due to a missing authorization check in the taxopress_ai_add_post_term AJAX function. Authenticated attackers with Contributor-level access or higher can add or modify terms (tags, categories) on any post, including those they do not have permission to edit, by specifying a target post ID.

Vulnerable Code

// Within the plugin's AJAX handler for AI Autotagger functionality
function taxopress_ai_add_post_term() {
    check_ajax_referer('taxopress_ai_nonce', 'nonce');

    $post_id  = isset($_POST['post_id']) ? (int)$_POST['post_id'] : 0;
    $term     = isset($_POST['term']) ? sanitize_text_field($_POST['term']) : '';
    $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field($_POST['taxonomy']) : 'post_tag';

    if ($post_id > 0 && !empty($term)) {
        // MISSING: current_user_can('edit_post', $post_id) check
        wp_set_post_terms($post_id, $term, $taxonomy, true);
        wp_send_json_success();
    }
    wp_send_json_error();
}

Security Fix

--- a/inc/class.admin.php
+++ b/inc/class.admin.php
@@ -10,6 +10,10 @@
     $term     = isset($_POST['term']) ? sanitize_text_field($_POST['term']) : '';
     $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field($_POST['taxonomy']) : 'post_tag';

+    if (!current_user_can('edit_post', $post_id)) {
+        wp_send_json_error(__('You do not have permission to edit this post.', 'simple-tags'));
+    }
+
     if ($post_id > 0 && !empty($term)) {
         wp_set_post_terms($post_id, $term, $taxonomy, true);
         wp_send_json_success();

Exploit Outline

To exploit this vulnerability, an attacker must have at least Contributor-level access to the WordPress dashboard. First, the attacker logs in and accesses the Post Editor (e.g., by creating a draft post) to retrieve the 'taxopress_ai_nonce' from the localized script parameters (usually found in the taxopress_admin_params JavaScript object). Next, the attacker identifies a target post ID they do not own, such as an administrator's post. Finally, the attacker sends an AJAX POST request to wp-admin/admin-ajax.php with the action 'taxopress_ai_add_post_term', providing the target post_id, the desired tag or category in the 'term' parameter, the taxonomy slug, and the acquired nonce. Because the function lacks a capability check for the specific post_id, the plugin will add the term to the target post despite the attacker lacking edit permissions.

Check if your site is affected.

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