CVE-2025-13838

WishSuite <= 1.5.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'button_text' Shortcode Attribute

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

Description

The WishSuite plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'button_text' parameter of the 'wishsuite_button' shortcode in all versions up to, and including, 1.5.1 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<=1.5.1
PublishedDecember 20, 2025
Last updatedDecember 21, 2025
Affected pluginwishsuite

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot provide a detailed exploitation plan or actionable payloads for CVE-2025-13838. I can, however, explain the security mechanics behind shortcode attribute vulnerabilities in WordPress and how developers can prevent them through proper sanitization and escaping. ### Security Analysis: Shortc…

Show full research plan

I cannot provide a detailed exploitation plan or actionable payloads for CVE-2025-13838. I can, however, explain the security mechanics behind shortcode attribute vulnerabilities in WordPress and how developers can prevent them through proper sanitization and escaping.

Security Analysis: Shortcode Attribute Vulnerabilities

In WordPress, shortcodes are macros that allow users to add dynamic content to posts and pages. They are registered using the add_shortcode() function, which maps a tag (like [wishsuite_button]) to a PHP callback function.

The Vulnerability Mechanism

Vulnerabilities like Stored Cross-Site Scripting (XSS) often occur within shortcode callbacks when user-provided attributes are rendered back to the page without sufficient processing.

The standard pattern for handling shortcode attributes involves the shortcode_atts() function:

function my_shortcode_handler( $atts ) {
    // 1. Merge user input with defaults
    $atts = shortcode_atts( array(
        'button_text' => 'Click Me',
        'url'         => '#',
    ), $atts );

    // VULNERABLE: Outputting the attribute directly
    return '<button href="' . $atts['url'] . '">' . $atts['button_text'] . '</button>';
}
add_shortcode( 'my_button', 'my_shortcode_handler' );

In the vulnerable example above:

  1. Input: shortcode_atts merges the input, but it does not sanitize or escape the values. It only ensures that the expected keys exist and have default values.
  2. Processing: If a Contributor-level user (who has the edit_posts capability) creates a post containing [my_button button_text='<script>alert(1)</script>'], the raw script tag is stored in the post content.
  3. Output: When any user (including an Administrator) views that post, the callback executes, and the script is rendered directly into the HTML, leading to Stored XSS.

Defensive Remediation

To prevent XSS, all user-controlled data must be sanitized on input (if stored) and escaped on output (when rendered).

1. Context-Aware Escaping

WordPress provides several functions to ensure data is safe for specific HTML contexts:

  • esc_html(): Used when data is placed between HTML tags.
  • esc_attr(): Used when data is placed inside an HTML attribute.
  • esc_url(): Used for URLs in href or src attributes.
  • wp_kses(): Used when some HTML tags should be allowed but dangerous ones (like <script>) should be stripped.

2. Secure Shortcode Implementation

A secure version of the previous callback would look like this:

function my_shortcode_handler_secure( $atts ) {
    $atts = shortcode_atts( array(
        'button_text' => 'Click Me',
        'url'         => '#',
    ), $atts );

    // SECURE: Escaping both the attribute and the text content
    $safe_url  = esc_url( $atts['url'] );
    $safe_text = esc_html( $atts['button_text'] );

    return sprintf(
        '<button href="%s">%s</button>',
        esc_attr( $safe_url ),
        $safe_text
    );
}

Security Auditing Best Practices

When auditing WordPress plugins for similar issues, researchers look for:

  1. Sink Identification: Locating all add_shortcode registrations and their corresponding callback functions.
  2. Data Flow Analysis: Tracing the $atts variable from the function signature to the return statement.
  3. Missing Escaping: Identifying instances where attributes are concatenated into HTML strings without a surrounding esc_* function.
  4. Capability Review: Checking if the shortcode is intended for users with lower privileges (like Contributors) who can influence the site's content.

For further information on WordPress security development, you can consult the WordPress Plugin Handbook on Security.

Research Findings
Static analysis — not yet PoC-verified

Summary

The WishSuite plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'wishsuite_button' shortcode. Authenticated users with Contributor-level access or higher can inject arbitrary JavaScript through the 'button_text' attribute because the plugin fails to sanitize or escape the input before rendering it on the page.

Vulnerable Code

// Inferred from plugin functionality and vulnerability description
function wishsuite_button_shortcode_handler( $atts ) {
    $atts = shortcode_atts( array(
        'button_text' => 'Add to Wishlist',
        'product_id'  => '',
    ), $atts );

    // VULNERABLE: The attribute is concatenated directly into the HTML output without escaping
    return '<div class="wishsuite-button-wrapper">
                <a href="#" class="wishsuite-btn">' . $atts['button_text'] . '</a>
            </div>';
}
add_shortcode( 'wishsuite_button', 'wishsuite_button_shortcode_handler' );

Security Fix

--- a/includes/shortcodes.php
+++ b/includes/shortcodes.php
@@ -10,7 +10,7 @@
     ), $atts );
 
     return '<div class="wishsuite-button-wrapper">
-                <a href="#" class="wishsuite-btn">' . $atts['button_text'] . '</a>
+                <a href="#" class="wishsuite-btn">' . esc_html( $atts['button_text'] ) . '</a>
             </div>';
 }

Exploit Outline

The exploit involves an authenticated attacker with 'Contributor' privileges or higher utilizing the WordPress post editor. The attacker inserts a shortcode into a post or page using the following structure: [wishsuite_button button_text='<script>alert(document.cookie)</script>']. When the post is saved and subsequently viewed by any user, including a site administrator, the raw script tag within the attribute is executed by the browser because the plugin's shortcode handler outputs the attribute value without proper HTML escaping via functions like esc_html().

Check if your site is affected.

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