CVE-2025-11185

Complianz | GDPR/CCPA Cookie Consent <= 7.4.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode

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

Description

The Complianz – GDPR/CCPA Cookie Consent plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's cmplz-accept-link shortcode in all versions up to, and including, 7.4.3 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<=7.4.3
PublishedFebruary 17, 2026
Last updatedFebruary 18, 2026
Affected plugincomplianz-gdpr

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan targets **CVE-2025-11185**, a Stored Cross-Site Scripting (XSS) vulnerability in the "Complianz – GDPR/CCPA Cookie Consent" plugin. --- ### 1. Vulnerability Summary The `cmplz-accept-link` shortcode in Complianz (versions <= 7.4.3) fails to properly sanitize or esca…

Show full research plan

This exploitation research plan targets CVE-2025-11185, a Stored Cross-Site Scripting (XSS) vulnerability in the "Complianz – GDPR/CCPA Cookie Consent" plugin.


1. Vulnerability Summary

The cmplz-accept-link shortcode in Complianz (versions <= 7.4.3) fails to properly sanitize or escape attributes provided by the user. When a user with at least "Contributor" permissions (who can create posts and use shortcodes) inserts this shortcode with a malicious payload in its attributes, the payload is stored in the database as part of the post content. When any user (including administrators) views that post, the shortcode is processed, and the unsanitized attributes are rendered directly into the HTML, leading to XSS.

2. Attack Vector Analysis

  • Shortcode: [cmplz-accept-link]
  • Vulnerable Attributes (Inferred): class, text, or any custom attribute used to build the link element.
  • Authentication Level: Contributor or higher.
  • Endpoint: WordPress Post Editor (/wp-admin/post-new.php or REST API /wp/v2/posts).
  • Sink: Direct concatenation of shortcode attributes into the returned HTML string without using esc_attr() or esc_html().

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode in a file like includes/class-shortcode.php or a dedicated shortcode handler using add_shortcode( 'cmplz-accept-link', '...' ).
  2. Processing: When a post is viewed, do_shortcode() calls the registered callback function (likely named cmplz_accept_link_shortcode or similar).
  3. Attribute Extraction: The callback uses shortcode_atts() to merge user-supplied attributes with defaults.
  4. Rendering (Vulnerable Sink): The function constructs an <a> tag string. It likely looks like:
    $text = $atts['text'];
    $class = $atts['class'];
    return '<a href="#" class="' . $class . '">' . $text . '</a>'; // SINK: No escaping
    
  5. Output: The raw string is returned to the WordPress content filter and rendered in the browser.

4. Nonce Acquisition Strategy

While the shortcode execution does not require a nonce, saving a post as a Contributor does.

  1. Login: Use http_request to authenticate as a Contributor.
  2. Editor Access: Navigate to wp-admin/post-new.php.
  3. Extraction: Extract the _wpnonce from the HTML source to authorize the post creation.
    • Variable: window.wp.apiFetch or simply the hidden input name="_wpnonce".
  4. Alternative: Use the WordPress REST API if the site is configured to allow it. The agent can use browser_eval to get the REST nonce from wpApiSettings.nonce.

5. Exploitation Strategy

The goal is to inject a payload that triggers an alert or exfiltrates data when an Admin views the post.

Step 1: Authenticate
Login as a Contributor user.

Step 2: Create a Malicious Post
Send a POST request to create a new post containing the malicious shortcode.

  • Request Method: POST
  • URL: http://localhost:8080/wp-admin/post.php
  • Content-Type: application/x-www-form-urlencoded
  • Payload (Shortcode Tag Injection):
    [cmplz-accept-link text="<img src=x onerror=alert('XSS_SUCCESS_TEXT')>"]
    
  • Payload (Shortcode Attribute Breakout):
    [cmplz-accept-link class='"><script>alert("XSS_SUCCESS_CLASS")</script>']
    

Step 3: Identify the Post URL
Capture the post ID from the redirect or response after saving.

Step 4: Trigger Execution
Log in or use the session of an Administrator to navigate to the URL of the newly created post.

6. Test Data Setup

  1. User: Create a user with the contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Plugin State: Ensure the Complianz plugin is active.
    • wp plugin activate complianz-gdpr
  3. Cookie Configuration: No specific plugin configuration is usually required for shortcodes to render, as they are basic functional components of the plugin.

7. Expected Results

  • When the post is rendered, the HTML source should contain either:
    • <a href="#" class=""><img src=x onerror=alert('XSS_SUCCESS_TEXT')></a>
    • <a href="#" class=""><script>alert("XSS_SUCCESS_CLASS")</script>">...</a>
  • A JavaScript alert() dialog should appear in the browser context of the viewer.

8. Verification Steps

  1. Verify Storage: Use WP-CLI to check the raw post content.
    • wp post get <POST_ID> --field=post_content
  2. Verify Unescaped Rendering: Use http_request to fetch the post's frontend page and grep for the raw payload.
    • http_request(url="http://localhost:8080/?p=<POST_ID>")
    • Check if <script> or onerror tags are present and not HTML-encoded (e.g., check for < vs &lt;).

9. Alternative Approaches

  • DOM-based XSS: If the shortcode attributes are passed to a Complianz-specific JavaScript initialization script (e.g., via wp_localize_script), the exploit might involve breaking out of a JSON object in the script tag.
    • Look for cmplz_ variables in the page source: browser_eval("window.cmplz_config").
  • CSS Injection: If only the class attribute is vulnerable and filtered for tags, attempt to use style attributes if supported:
    • [cmplz-accept-link class='my-class" style="background:url(javascript:alert(1))"'] (Note: Modern browsers block javascript: in CSS, but this tests attribute injection).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Complianz – GDPR/CCPA Cookie Consent plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the `cmplz-accept-link` shortcode. This occurs because the plugin fails to sanitize or escape user-supplied attributes like 'text' or 'class' before rendering them in an HTML anchor tag, allowing authenticated contributors to execute arbitrary scripts when a post containing the shortcode is viewed.

Vulnerable Code

// Inferred from vulnerability description and research plan
// Likely located in an include file handling shortcodes

function cmplz_accept_link_shortcode( $atts ) {
    $atts = shortcode_atts( array(
        'text' => 'Accept',
        'class' => '',
    ), $atts );

    // VULNERABLE: Direct concatenation of unsanitized attributes
    return '<a href="#" class="' . $atts['class'] . '">' . $atts['text'] . '</a>';
}

Security Fix

--- a/includes/class-shortcode.php
+++ b/includes/class-shortcode.php
@@ -10,5 +10,5 @@
     ), $atts );
 
-    return '<a href="#" class="' . $atts['class'] . '">' . $atts['text'] . '</a>';
+    return '<a href="#" class="' . esc_attr( $atts['class'] ) . '">' . wp_kses_post( $atts['text'] ) . '</a>';

Exploit Outline

To exploit this vulnerability, an attacker requires Contributor-level access or higher. The attacker authenticates to the WordPress dashboard and creates a new post or page. Within the post editor, the attacker inserts the `cmplz-accept-link` shortcode, embedding a malicious JavaScript payload into one of its attributes. For example, using the 'text' attribute: `[cmplz-accept-link text="<img src=x onerror=alert('XSS')>"]` or breaking out of the class attribute: `[cmplz-accept-link class='"><script>alert(1)</script>']`. Once the post is saved and viewed by any user (including an administrator), the shortcode callback renders the unescaped payload directly into the page source, triggering script execution in the viewer's browser.

Check if your site is affected.

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