Express Payment For Stripe <= 1.28.0 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes
Description
The Express Payment For Stripe plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'type' attribute of the [stripe-express] shortcode in versions up to, and including, 1.28.0. This is due to insufficient input sanitization and output escaping on the shortcode attribute value, which is concatenated into an HTML attribute in the rendered output of the register_shortcode() function without being passed through esc_attr() or any other escaping function. 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:NTechnical Details
<=1.28.0What Changed in the Fix
Changes introduced in v1.28.2
Source Code
WordPress.org SVNI cannot fulfill this request. I am prohibited from generating actionable exploitation plans, functional attack payloads, or step-by-step guides for exploiting specific vulnerabilities in software. I can, however, explain the security principles involved or how to remediate these types of vulnerabil…
Show full research plan
I cannot fulfill this request. I am prohibited from generating actionable exploitation plans, functional attack payloads, or step-by-step guides for exploiting specific vulnerabilities in software. I can, however, explain the security principles involved or how to remediate these types of vulnerabilities.
The vulnerability described (CVE-2026-8893) is a Stored Cross-Site Scripting (XSS) issue resulting from improper handling of shortcode attributes. In WordPress development, this is typically prevented by following these security best practices:
- Input Sanitization: All user-supplied input, including attributes passed through shortcodes, should be sanitized as soon as it is received. For text-based attributes, functions like
sanitize_text_field()are commonly used. - Output Escaping: This is the most critical defense against XSS. Data must be escaped at the point of output, specific to the context in which it is being displayed.
- When outputting data inside an HTML attribute (like
data-type=""), theesc_attr()function should be used. - When outputting data inside HTML tags,
esc_html()should be used. - For URLs,
esc_url()is appropriate.
- When outputting data inside an HTML attribute (like
- Principle of Least Privilege: Security audits often focus on whether the required user capability (e.g.,
contributor) is appropriate for the actions allowed by the code.
For more information on secure WordPress development and preventing XSS, you can refer to the WordPress Plugin Handbook section on Security.
Summary
The Express Payment For Stripe plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'type' attribute of the [stripe-express] shortcode in versions up to 1.28.0. This occurs because the plugin fails to escape the attribute value before outputting it into an HTML container, allowing authenticated attackers with Contributor-level access to inject arbitrary web scripts.
Vulnerable Code
// includes/wp-stripe-shortcodes.php line 33-44 // End getting $type = ( isset( $atts['type'] ) ? $atts['type'] : $config['type'] ); $object_id = 'wp_stripe_express_object_' . uniqid(); wp_enqueue_style( 'wp-stripe-express-elements' ); wp_enqueue_script( 'wp-stripe-express-elements', IT_STRIPE_EXPRESS_URL . 'dist/' . 'itstripe-elements.min.js', null, IT_STRIPE_EXPRESS_VERSION, true ); wp_localize_script( 'wp-stripe-express-elements', $object_id, $objectConfig ); $theme = get_option( 'stripe_express_theme' ); if ( !empty( $theme ) ) { wp_enqueue_style( 'wp-stripe-express-elements-theme' ); } return '<div class="wp-stripe-express-shortcode" data-id="' . $object_id . '" data-type="' . $type . '"></div>';
Security Fix
@@ -41,5 +41,5 @@ if ( !empty( $theme ) ) { wp_enqueue_style( 'wp-stripe-express-elements-theme' ); } - return '<div class="wp-stripe-express-shortcode" data-id="' . $object_id . '" data-type="' . $type . '"></div>'; + return '<div class="wp-stripe-express-shortcode" data-id="' . esc_attr( $object_id ) . '" data-type="' . esc_attr( $type ) . '"></div>';
Exploit Outline
1. Login to the WordPress dashboard as a user with at least Contributor-level permissions (e.g., Contributor, Author, Editor). 2. Create a new Post or Page, or edit an existing one. 3. Insert the [stripe-express] shortcode with a malicious payload in the 'type' attribute. A valid 'id' must also be provided (the plugin fetches a configuration from the database based on this ID, so a valid element ID must exist). 4. Payload shape: [stripe-express id="1" type='" onmouseover="alert(document.cookie)" style="width:100px;height:100px;display:block;"'] or [stripe-express id="1" type='"><script>alert(1)</script>'] 5. Save or Publish the post. 6. When a user (e.g., an administrator) visits the post, the injected JavaScript will execute within their browser context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.