Research · 9 min read

WordPress Arbitrary File Upload Vulnerability: Divi Form Builder

By WP Vanguard Team

WordPress Arbitrary File Upload Vulnerability: Divi Form Builder

On July 1, 2026, researchers disclosed CVE-2026-5524, a critical, unauthenticated arbitrary file upload vulnerability in Divi Form Builder, affecting every version up to and including 5.1.8. It carries a CVSS score of 9.8. The fix landed in version 5.1.9. No login, no nonce, no privileged account: any visitor who can reach a form built with the plugin can potentially drop a working webshell on the server.

What makes this one worth a closer read isn't that a check was missing. A check was there. It just took its rules from the same request it was supposed to be inspecting. The plugin built its file-extension allowlist out of a POST parameter the attacker controls, which means the attacker wasn't bypassing validation, they were authoring it. That distinction is the whole story, and it's a pattern worth checking your own code for, regardless of whether you run this specific plugin.

A CVSS score of 9.8 sits at the top of the critical band, and the three inputs that push it there are exactly the conditions present here: the attack runs over the network, it takes low complexity to pull off, and it needs no privileges and no user interaction. Most critical WordPress bugs require at least one of those to be harder, an authenticated role, a social-engineering step, a race condition. This one asks for none of that. A form that's already live on the site is the only precondition.

How the flaw works in do_image_upload()

The vulnerability lives in a function called do_image_upload(). When a site visitor submits a file through a Divi Form Builder upload field, the plugin needs to decide whether the extension is acceptable before it writes the file to disk. That decision should be the server's alone to make. Instead, the function reads a POST parameter named acceptFileTypes and interpolates it directly into the regular expression used to test the uploaded filename.

In plain terms: the client sends the plugin a string describing what file types are okay, and the plugin trusts that string enough to build its security check out of it. There's no character allowlist on the parameter, no comparison against a fixed server-side list, no rejection of unexpected values. Whatever pattern arrives in the request becomes the pattern the file gets checked against.

That's the mechanism. It doesn't require a clever payload or a chain of bugs. It requires noticing that a parameter named acceptFileTypes sounds like configuration but behaves like code, because a regex built from unfiltered input is functionally a tiny program the client gets to write.

Who's affected

Every Divi Form Builder installation running 5.1.8 or earlier is vulnerable, and there's no configuration flag that turns this off. Because the endpoint doesn't check for authentication, an attacker doesn't need a contributor account, a stolen session, or a phished admin. They need a page with a Divi Form Builder upload field that a browser can reach, which describes most sites that shipped a contact form, application form, or support-ticket form with this plugin active.

This is also not the first time a form plugin's upload handling has been the weak point. We've covered a similar class of bug in the Ninja Forms file upload vulnerability, where a different set of assumptions about what a submitted file could be led to the same outcome: a file the server should never have accepted, accepted anyway. Form plugins are a recurring target precisely because they're designed to take arbitrary input from anonymous visitors and write some of it to disk.

If your site runs Divi Form Builder and you haven't confirmed the installed version in the last few weeks, that's the first thing to check, before anything else in this post.

There's no capability check or configuration toggle that shrinks the exposure here. Sites that keep Divi Form Builder active purely for an internal or gated form aren't automatically safe either, since the vulnerable upload handler is a plugin-level endpoint rather than something scoped to a specific form's visibility settings. The relevant question isn't which forms are public on the front end, it's whether the plugin is active at all and whether its version predates 5.1.9.

When the client writes the allowlist, it isn't one

Here's the principle this bug exists to teach: validation rules have to be defined on the server, as static values the server owns, and nothing arriving in a request should ever be treated as policy. A request can carry data. It cannot carry the rules for judging that data. Once you let a parameter shape the logic that's supposed to constrain parameters, you've handed the attacker the pen they use to write themselves an exception.

It's easy to see the pattern in isolated code. It's much easier to miss when it's buried inside a helper that looks defensive on its face, "acceptFileTypes," a name that reads like a safety feature.

Here's the anti-pattern, reduced to its essence:

// Anti-pattern: the "rule" comes from the request
$allowed_pattern = '/\.(' . $_POST['acceptFileTypes'] . ')$/i';
if (preg_match($allowed_pattern, $filename)) {
    move_uploaded_file($tmp_path, $target_path);
}

Whatever string shows up in acceptFileTypes becomes the rule. Send php5|phar|phtml and the regex will happily match those extensions, because the regex is whatever you told it to be.

Compare that to a static, server-owned check:

// Server defines the policy; the request only supplies data to test against it
$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif'];
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (in_array($extension, $allowed_extensions, true)) {
    move_uploaded_file($tmp_path, $target_path);
}

The second version has no input path into its own logic. pathinfo() extracts the extension, the hardcoded array defines what's acceptable, and nothing the client sends can change either one. That's the entire fix, conceptually: move the list of acceptable extensions out of the request and into code the attacker can't touch.

Note the true as the third argument to in_array(), too. Strict comparison matters here for the same reason static rules matter: a loose comparison can be tricked by a value that looks equal but isn't, and a security check is exactly the wrong place to leave that kind of ambiguity in. None of this is exotic. It's the difference between checking a value against a known-good set and building the known-good set out of the value.

The same failure shows up under different names across the ecosystem: a "format" parameter that gets passed to a template engine, a "sort" field interpolated into a SQL ORDER BY clause, a "type" value used to pick a class to instantiate. Anywhere a request field ends up inside logic rather than being compared against logic, ask who really controls that field. If the answer is "the attacker," it's not validation.

Why a .htaccess upload guard is a weak second line

Divi Form Builder didn't rely solely on extension checking. Its uploads directory also carries a .htaccess file meant to stop PHP execution as a backstop. That's a reasonable idea in principle, but the specific rule only blocked the .php extension, and Apache's handler configuration on many hosts will still execute a range of other extensions as PHP: .phtml, .phar, .php5, .php7, and similar variants, depending on the server's AddHandler or AddType directives.

An attacker who can supply the extension allowlist doesn't need .php. They can name an extension the .htaccess rule never anticipated, upload through the flawed regex check, and let the server's own PHP handler execute the result. The guard wasn't wrong to exist. It was wrong to be treated as sufficient on its own, standing in for the extension validation that should have caught the file before it ever reached the filesystem.

This is worth internalizing past this one plugin: a directory-level execution block is a mitigation for when validation fails, not a substitute for validation. It should never be the only thing standing between an upload field and code execution, because the set of PHP-executable extensions on a given Apache config is rarely a fixed, well-known list, and a rule written against .php alone was already incomplete before this CVE ever existed.

If a plugin does get this far, the payload that lands is typically a webshell, the kind of small PHP file that gives an attacker a persistent command interface. We've written about what those look like and where they hide in PHP backdoors in WordPress, which is worth reading if you're auditing a site that might have been touched.

What to do now

Update Divi Form Builder to 5.1.9 or later immediately. That's the fix, and there's no partial mitigation that replaces it, since the vulnerable code path is unauthenticated and reachable from any public-facing form built with the plugin.

If you were running 5.1.8 or earlier at any point before you patched, don't assume you're clean just because the site looks normal. Check these specific things:

If you find anything matching those indicators, treat the site as compromised rather than patched-and-fine. Our signs your WordPress site has been hacked guide covers the broader checklist for confirming a breach, and our WordPress malware removal guide walks through cleanup once you've confirmed one. Neither substitutes for updating the plugin first; they matter for anyone who was running the vulnerable version before this post existed.

WP Vanguard's scanner flags plugins running versions with known CVEs like this one, including the specific version range affected here, so you catch the exposure window before an opportunistic scan finds it first.

References

wordpress-arbitrary-file-upload-vulnerability cve-2026-5524 divi-form-builder remote-code-execution unauthenticated-vulnerability

Related reading

Check Your WordPress Site Security

Free scan, no login required. Find vulnerabilities before attackers do.

Scan Your Site Free

Get weekly WordPress security tips

Vulnerability alerts, plugin updates, and security guides. No spam. Unsubscribe any time.

WP Vanguard is built by Wbcom Designs, makers of Reign, Jetonomy, Listora, and more. Explore our WordPress products →
← Back to Blog