CVE-2026-39654

Simple HTML Sitemap <= 3.8 - Authenticated (Author+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Simple HTML Sitemap plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.8 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with author-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.8
PublishedFebruary 15, 2026
Last updatedApril 15, 2026
Affected pluginwp-simple-html-sitemap
Research Plan
Unverified

This research plan outlines the methodology for analyzing and exploiting **CVE-2026-39654** in the **WP Simple HTML Sitemap** plugin. --- ### 1. Vulnerability Summary The **WP Simple HTML Sitemap** plugin (versions <= 3.8) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exist…

Show full research plan

This research plan outlines the methodology for analyzing and exploiting CVE-2026-39654 in the WP Simple HTML Sitemap plugin.


1. Vulnerability Summary

The WP Simple HTML Sitemap plugin (versions <= 3.8) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin handles user-supplied input (likely via shortcode attributes or post metadata) and renders it on the frontend or backend without sufficient sanitization (e.g., sanitize_text_field) or output escaping (e.g., esc_html or esc_attr). An attacker with Author level permissions can inject arbitrary JavaScript that executes when any user (including Administrators) views the affected page.

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php (Standard WordPress post/page editor).
  • Action: Saving or publishing a post/page containing a malicious shortcode.
  • Vulnerable Component: The shortcode handler for the sitemap.
  • Shortcode Tag (Inferred): [wp_simple_html_sitemap] or [simple-html-sitemap].
  • Vulnerable Parameters (Inferred): Shortcode attributes such as title, label, class, or id.
  • Authentication: Requires an account with at least Author privileges (the ability to create and publish posts/pages).

3. Code Flow (Inferred)

  1. The plugin registers a shortcode in its main file (e.g., wp-simple-html-sitemap.php) using add_shortcode( 'wp_simple_html_sitemap', 'callback_function' ).
  2. The callback_function receives an $atts array containing user-defined attributes from the shortcode.
  3. The plugin fails to sanitize these attributes upon receipt.
  4. The attributes are then used to build an HTML string (e.g., <h2 class="sitemap-title">$title</h2>).
  5. The plugin returns or echoes the HTML string without using esc_html() or esc_attr() on the attributes.
  6. When a user views the page where the shortcode is placed, the injected script executes.

4. Nonce Acquisition Strategy

Since this vulnerability is exploited through the standard WordPress post editor, the "Store" phase relies on standard WordPress core nonces for saving posts.

  1. Authentication: Log in as an Author user.
  2. Navigation: Navigate to wp-admin/post-new.php?post_type=page.
  3. Extraction:
    • The _wpnonce and _wp_http_referer are required for the POST request to post.php.
    • The execution agent should use browser_navigate to the editor page and then use browser_eval to extract the _wpnonce value from the hidden input field:
      browser_eval("document.querySelector('#_wpnonce').value").

5. Exploitation Strategy

Step 1: Authentication and Nonce Retrieval

Log in as the Author and capture the necessary post-submission nonce.

Step 2: Inject Stored XSS via Shortcode

Submit a request to create a page containing the malicious shortcode.

  • Request Method: POST
  • URL: http://localhost:8080/wp-admin/post.php
  • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: editpost
    • post_ID: (obtained from the post-new.php page load)
    • _wpnonce: (extracted nonce)
    • post_title: Sitemap Test
    • content: [wp_simple_html_sitemap title='<script>alert(document.cookie)</script>'] (Inferred attribute name)
    • publish: Publish

Step 3: Trigger the XSS

Navigate to the newly created page URL on the frontend to trigger the script execution.

6. Test Data Setup

  1. Plugin Installation: Ensure wp-simple-html-sitemap version 3.8 is installed and active.
  2. User Creation:
    wp user create attacker attacker@example.com --role=author --user_pass=password
    
  3. Discovery: Determine the exact shortcode name and attributes by searching the plugin directory:
    grep -rn "add_shortcode" /var/www/html/wp-content/plugins/wp-simple-html-sitemap/
    

7. Expected Results

  • The POST request to post.php should return a 302 Redirect to the post editor with message=1 (Post published).
  • When navigating to the published page, a JavaScript alert box displaying the user's cookies should appear.
  • Viewing the page source should show the raw <script> tag inside the sitemap's container elements.

8. Verification Steps (Post-Exploit)

Confirm the payload is stored in the database:

wp db query "SELECT post_content FROM wp_posts WHERE post_title='Sitemap Test' LIMIT 1;"

Check if the output in the frontend is truly unescaped:

# Using the http_request tool to fetch the page content
# Look for the literal string: <script>alert(document.cookie)</script>

9. Alternative Approaches

If shortcode attributes are sanitized, check the Post Title vector:

  1. As an Author, create a post with the title: <img src=x onerror=alert(1)>.
  2. Create a separate page with the sitemap shortcode: [wp_simple_html_sitemap].
  3. If the plugin renders the list of post titles without escaping, the XSS will trigger when viewing the sitemap page.

Verification for Alternative:

grep -rn "the_title" /var/www/html/wp-content/plugins/wp-simple-html-sitemap/
# Check if it uses get_the_title() followed by echo without esc_html()
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Simple HTML Sitemap plugin for WordPress (<= 3.8) is vulnerable to Stored Cross-Site Scripting (XSS) because it fails to sanitize and escape shortcode attributes. Authenticated attackers with Author-level permissions can inject malicious scripts into pages by using crafted shortcode attributes, which then execute when any user views the affected sitemap page.

Vulnerable Code

// wp-simple-html-sitemap/wp-simple-html-sitemap.php (Inferred shortcode handler)

function wp_simple_html_sitemap_shortcode_handler($atts) {
    $a = shortcode_atts(array(
        'title' => 'Sitemap',
        'class' => 'sitemap-list',
    ), $atts);

    // Vulnerable output: Attributes are echoed directly without esc_html() or esc_attr()
    $output = '<div class="' . $a['class'] . '">';
    $output .= '<h2>' . $a['title'] . '</h2>';
    
    // ... (rest of the sitemap generation code)

    return $output;
}

Security Fix

--- wp-simple-html-sitemap/wp-simple-html-sitemap.php
+++ wp-simple-html-sitemap/wp-simple-html-sitemap.php
@@ -10,8 +10,8 @@
     ), $atts);
 
-    $output = '<div class="' . $a['class'] . '">';
-    $output .= '<h2>' . $a['title'] . '</h2>';
+    $output = '<div class="' . esc_attr($a['class']) . '">';
+    $output .= '<h2>' . esc_html($a['title']) . '</h2>';
 
     // ... (rest of the sitemap generation code)

Exploit Outline

1. Authentication: Log in to the WordPress dashboard as a user with at least Author permissions. 2. Nonce Retrieval: Navigate to the 'Add New Post' or 'Add New Page' screen to retrieve the necessary `_wpnonce` and `post_ID` for post creation. 3. Payload Injection: Create or update a post/page and include the plugin's sitemap shortcode (likely `[wp_simple_html_sitemap]`) with a malicious attribute payload, for example: `[wp_simple_html_sitemap title="<script>alert(document.cookie)</script>"]`. 4. Execution: Publish the post and navigate to its permalink on the frontend. The injected script will execute in the context of the user's browser.

Check if your site is affected.

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