CVE-2026-0737

Shortcodes Ultimate <= 7.4.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'su_lightbox' Shortcode

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

Description

The WP Shortcodes Plugin - Shortcodes Ultimate plugin for WordPress is vulnerable to Stored Cross-Site Scripting in all versions up to, and including, 7.4.7. This is due to insufficient input sanitization and output escaping in the 'src' attribute of the su_lightbox shortcode. 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<=7.4.7
PublishedApril 3, 2026
Last updatedApril 4, 2026
Affected pluginshortcodes-ultimate

What Changed in the Fix

Changes introduced in v7.4.8

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-0737 ## 1. Vulnerability Summary The **Shortcodes Ultimate** plugin (<= 7.4.7) is vulnerable to **Stored Cross-Site Scripting (XSS)** via the `su_lightbox` shortcode. The vulnerability exists because the plugin insufficiently sanitizes the `src` attribute. Wh…

Show full research plan

Exploitation Research Plan - CVE-2026-0737

1. Vulnerability Summary

The Shortcodes Ultimate plugin (<= 7.4.7) is vulnerable to Stored Cross-Site Scripting (XSS) via the su_lightbox shortcode. The vulnerability exists because the plugin insufficiently sanitizes the src attribute. While it performs a weak check for the string javascript and uses esc_attr() on the output, it fails to account for:

  1. Protocol Bypasses: Bypassing the javascript: check using data: URIs.
  2. JavaScript Sink Injection: The frontend JavaScript (Magnific Popup) reads the data-mfp-src attribute and uses it to dynamically construct HTML elements (like <img> or <iframe>). During this process, attribute-escaped characters (like &quot;) are interpreted as real quotes, allowing an attacker to break out of the constructed HTML tag's attributes.

2. Attack Vector Analysis

  • Endpoint: Standard WordPress post/page creation/edition.
  • Shortcode: [su_lightbox]
  • Vulnerable Attribute: src
  • Authentication Level: Authenticated (Contributor+). Contributors can create posts and use shortcodes by default.
  • Preconditions: The su_option_unsafe_features setting is typically on by default, but this vulnerability persists regardless of that setting as it lies in the core shortcode rendering logic.

3. Code Flow

  1. Entry Point: A user with Contributor+ permissions saves a post containing the [su_lightbox] shortcode.
  2. Processing: When the post is rendered, WordPress calls do_shortcode(), which triggers the registered callback su_shortcode_lightbox in includes/shortcodes/lightbox.php.
  3. Vulnerable Function: su_shortcode_lightbox($atts, $content)
    • Line 112: $atts['src'] = su_do_attribute($atts['src'], true); (Processes placeholders).
    • Line 114: if (strpos(strtolower($atts['src']), 'javascript') !== false) (Blacklist check for javascript: protocol).
    • Line 124: The src is passed to esc_attr() and embedded in a <span> tag:
      return '<span class="su-lightbox..." data-mfp-src="' . esc_attr($atts['src']) . '" ...>';
      
  4. Frontend Execution:
    • The plugin enqueues magnific-popup and su-shortcodes (includes/js/su-shortcodes.js).
    • The JS initializes the lightbox on elements with class .su-lightbox.
    • When a user clicks the lightbox trigger, Magnific Popup reads the data-mfp-src value using jQuery's .data() or .attr().
    • Sink: Magnific Popup uses this value to construct the modal content. If type="image", it creates an <img> tag. If type="iframe", it creates an <iframe>. Because it often uses string concatenation or jQuery's $() to build these elements, the payload executes.

4. Nonce Acquisition Strategy

No WordPress nonce is required to exploit this vulnerability because it is a Stored XSS triggered by the standard rendering of post content.

  • The shortcode is processed during the the_content filter execution.
  • The Contributor only needs to create or update a post, which uses standard WordPress nonces for the post.php or post-new.php endpoints. These are managed automatically by a logged-in session.

5. Exploitation Strategy

Step-by-Step Plan

  1. Login as Contributor: Authenticate with Contributor credentials.
  2. Create Post: Use the WordPress REST API or standard post creation to save a post containing the malicious shortcode.
  3. Inject Payload: Use a payload that bypasses the javascript check and breaks out of the JS-constructed attribute.

Malicious Payloads

Option A: Attribute Breakout (via Image type)
This payload uses a double quote to break out of the src attribute when Magnific Popup constructs the <img> tag.

[su_lightbox type="image" src='https://example.com/logo.png" onerror="alert(window.origin
Research Findings
Static analysis — not yet PoC-verified

Summary

The Shortcodes Ultimate plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'su_lightbox' shortcode due to insufficient input validation and output escaping. Authenticated attackers with contributor-level permissions or higher can inject arbitrary scripts through the 'src' attribute, which are then executed by the frontend Magnific Popup library when the lightbox trigger is processed.

Vulnerable Code

// includes/shortcodes/lightbox.php line 114
	if (strpos(strtolower($atts['src']), 'javascript') !== false) {
		return su_error_message('Lightbox', __('please specify correct source', 'shortcodes-ultimate'));
	}

---

// includes/shortcodes/lightbox.php line 124
	return '<span class="su-lightbox' . su_get_css_class($atts) . '" data-mfp-src="' . esc_attr($atts['src']) . '" data-mfp-type="' . sanitize_key($atts['type']) . '" data-mobile="' . sanitize_key($atts['mobile']) . '">' . do_shortcode($content) . '</span>';

Security Fix

--- includes/shortcodes/lightbox.php
+++ includes/shortcodes/lightbox.php
@@ -111,7 +111,10 @@
 
 	$atts['src'] = su_do_attribute($atts['src'], true);
 
-	if (strpos(strtolower($atts['src']), 'javascript') !== false) {
+	if (
+		strpos(strtolower($atts['src']), 'javascript') !== false ||
+		strpos(strtolower($atts['src']), 'data:') !== false
+	) {
 		return su_error_message('Lightbox', __('please specify correct source', 'shortcodes-ultimate'));
 	}
 
@@ -121,5 +124,5 @@
 	su_query_asset('js', 'magnific-popup');
 	su_query_asset('js', 'su-shortcodes');
 
-	return '<span class="su-lightbox' . su_get_css_class($atts) . '" data-mfp-src="' . esc_attr($atts['src']) . '" data-mfp-type="' . sanitize_key($atts['type']) . '" data-mobile="' . sanitize_key($atts['mobile']) . '">' . do_shortcode($content) . '</span>';
+	return '<span class="su-lightbox' . su_get_css_class($atts) . '" data-mfp-src="' . esc_url($atts['src']) . '" data-mfp-type="' . sanitize_key($atts['type']) . '" data-mobile="' . sanitize_key($atts['mobile']) . '">' . do_shortcode($content) . '</span>';
 }

Exploit Outline

The exploit targets the `su_lightbox` shortcode, which is available to any user with the ability to create or edit posts (Contributor+ by default). An attacker inserts a malicious shortcode like `[su_lightbox type="image" src='https://example.com/logo.png" onerror="alert(1)']Click Me[/su_lightbox]`. When a victim visits the page, the plugin renders the shortcode into a `<span>` element with the payload in the `data-mfp-src` attribute. The plugin's frontend JavaScript (Magnific Popup) reads this attribute to dynamically construct a modal element (e.g., an `<img>` tag). Because the JavaScript implementation does not properly re-sanitize the data when building the element's inner HTML or attributes, the injected quote breaks out of the `src` attribute, allowing the `onerror` handler to execute arbitrary JavaScript.

Check if your site is affected.

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