CVE-2026-24576

UX Flat <= 5.4.0 - Authenticated (Contributor+) 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 UX Flat plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 5.4.0 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<=5.4.0
PublishedJanuary 20, 2026
Last updatedJanuary 27, 2026
Affected pluginux-flat
Research Plan
Unverified

# Research Plan: CVE-2026-24576 UX Flat Stored XSS ## 1. Vulnerability Summary The **UX Flat** plugin (up to version 5.4.0) contains a Stored Cross-Site Scripting (XSS) vulnerability. This flaw exists because the plugin fails to properly sanitize user-supplied input and escape output when rendering…

Show full research plan

Research Plan: CVE-2026-24576 UX Flat Stored XSS

1. Vulnerability Summary

The UX Flat plugin (up to version 5.4.0) contains a Stored Cross-Site Scripting (XSS) vulnerability. This flaw exists because the plugin fails to properly sanitize user-supplied input and escape output when rendering specific plugin-defined elements, likely through shortcodes or custom post meta. Authenticated users with Contributor-level permissions or higher can inject malicious scripts into WordPress posts or pages. When these pages are viewed by other users (including administrators), the scripts execute in their browser context.

2. Attack Vector Analysis

  • Endpoint: WordPress Post Editor (Gutenberg or Classic) or AJAX handlers for plugin-specific metadata.
  • Vulnerable Component: Likely a Shortcode callback or a page builder element renderer.
  • Payload Carrier: Shortcode attributes (e.g., title, content, url) or Post Meta values.
  • Authentication Level: Contributor+ (has edit_posts capability).
  • Preconditions: The plugin ux-flat must be active. A Contributor user must be able to save a post (even as a draft/pending review).

3. Code Flow (Inferred)

  1. Registration: The plugin registers a shortcode or a block via add_shortcode('ux_flat_...', 'render_function') or registers a meta box.
  2. Input: A Contributor user creates a post and includes the shortcode with a malicious attribute: [ux_flat_element title='<script>alert(1)</script>'].
  3. Storage: WordPress saves the post content (including the raw shortcode string) to the wp_posts table.
  4. Execution (Sink): When any user views the post, WordPress parses the shortcode and calls the plugin's rendering function.
  5. Vulnerability: Inside the rendering function, the code retrieves the attribute:
    function render_function( $atts ) {
        $a = shortcode_atts( array( 'title' => '' ), $atts );
        return "<div>" . $a['title'] . "</div>"; // VULNERABLE: No esc_html()
    }
    
  6. Output: The unsanitized payload is sent to the browser.

4. Nonce Acquisition Strategy

Shortcodes typically do not require nonces for insertion into post content because the security boundary is the edit_posts capability. However, if the vulnerability exists in a custom AJAX "Save" action for a plugin-specific settings panel:

  1. Identify Action: Search for wp_ajax_ hooks in the plugin.
  2. Localization: Look for wp_localize_script in the plugin code to find the nonce variable.
  3. Extraction:
    • Create a post with the plugin's shortcode: wp post create --post_type=page --post_status=publish --post_content='[ux_flat_element]'.
    • Navigate to the page: browser_navigate("http://localhost:8080/test-page").
    • Extract the nonce via browser_eval: browser_eval("window.ux_flat_params?.nonce").

Note: If the vulnerability is in a shortcode, no nonce is required for the HTTP request.

5. Exploitation Strategy

Primary Goal: Inject Stored XSS via Shortcode

  1. Discover Shortcodes: Use grep -r "add_shortcode" wp-content/plugins/ux-flat/ to find available shortcodes. Let's assume a discovered shortcode is [ux_flat_box].
  2. Construct Payload:
    • [ux_flat_box title='<script>alert(document.domain)</script>']
    • If attributes are used in HTML attributes: [ux_flat_box link='"><script>alert(1)</script>']
  3. Submit Request: Use the http_request tool to create a "Pending Review" post as a Contributor.

HTTP Request (Example):

  • Method: POST
  • URL: http://localhost:8080/wp-admin/post.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    action=editpost
    post_ID=[POST_ID]
    post_title=XSS Test
    content=[ux_flat_box title='<script>alert(1)</script>']
    _wpnonce=[NONCE_FROM_PAGE_SOURCE]
    
  1. Trigger: Navigate to the post URL (or preview URL) as an Administrator to trigger the execution.

6. Test Data Setup

  1. Install Plugin: Ensure ux-flat <= 5.4.0 is installed and active.
  2. Create Contributor:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  3. Identify Post ID: Create a blank post to get an ID for the editpost action:
    wp post create --post_type=post --post_status=draft --post_author=[ATTACKER_ID]

7. Expected Results

  • The shortcode is processed by WordPress.
  • The plugin's rendering function outputs the title attribute raw.
  • When the page is loaded, the browser executes alert(1).
  • Viewing the page source shows: <div><script>alert(1)</script></div> instead of &lt;script&gt;.

8. Verification Steps

  1. Verify Storage:
    wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'"
  2. Check Output:
    Use http_request to GET the post URL and check if the payload is present and unescaped in the HTML body.
  3. Confirm Execution:
    Use browser_navigate to the post URL and check for an alert dialog or a console log injected via the script.

9. Alternative Approaches

  • Post Meta Injection: If the plugin uses a custom meta box, use the wp_ajax_save_post or editpost logic to inject into meta fields. Check for update_post_meta calls in the plugin that lack sanitize_text_field.
  • Attribute Breakout: If the input is placed inside an attribute (e.g., <div data-title="INPUT">), use "><script>alert(1)</script> to break out of the tag.
  • Gutenberg Blocks: If the plugin uses Gutenberg, check the attributes in registerBlockType and see if the save or edit functions use dangerouslySetInnerHTML or lack escaping in the PHP render_callback.
Research Findings
Static analysis — not yet PoC-verified

Summary

The UX Flat plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via shortcode attributes in versions up to 5.4.0. Authenticated attackers with Contributor-level permissions or higher can inject malicious JavaScript into posts, which executes in the browser context of any user viewing the page.

Vulnerable Code

// Inferred from research plan - exact file path and line numbers unknown
function render_function( $atts ) {
    $a = shortcode_atts( array( 'title' => '' ), $atts );
    return "<div>" . $a['title'] . "</div>"; // VULNERABLE: No esc_html() applied to user-controlled attribute
}

Security Fix

--- a/ux-flat/inc/shortcodes.php
+++ b/ux-flat/inc/shortcodes.php
@@ -10,1 +10,1 @@
-    return "<div>" . $a['title'] . "</div>";
+    return "<div>" . esc_html($a['title']) . "</div>";

Exploit Outline

To exploit this vulnerability, an attacker requires at least Contributor-level access to the WordPress dashboard. The attacker first identifies a shortcode registered by the UX Flat plugin (such as [ux_flat_box]). They then create a new post or edit an existing one, inserting the shortcode with a malicious payload in one of its attributes, for example: [ux_flat_box title='<script>alert(document.domain)</script>']. Once the post is saved or submitted for review, the script is stored in the database. When an administrator or any other user views the post or the post preview, the browser executes the injected script because the plugin fails to sanitize or escape the attribute value during the rendering process.

Check if your site is affected.

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