Forminator, the form and quiz builder plugin running on more than 600,000 WordPress sites, shipped a patch on July 31, 2026 for a bug that let an attacker with no account and no login upload a working PHP file to a vulnerable site. Security researcher daroo found it, Wordfence catalogued it as CVE-2026-15748 with a 9.8 out of 10 severity score, and the way the bug works is specific enough to be worth understanding even if you’ve never installed Forminator, because the same pattern shows up in other form plugins too.
What the bug let an attacker do
The flaw lives in a function called `handle_file_upload()`. Forminator, like most WordPress plugins that accept file uploads, keeps a blocklist of dangerous file extensions so a visitor can’t upload a `.php` file disguised as a form attachment. Wordfence found that the blocklist check used exact-key matching against MIME type keys, and that matching could be bypassed using pipe-alternative MIME type keys the blocklist logic never accounted for. Combine that with a public submission handler that trusted attacker-controlled upload field configuration injected through a forged Select field value, and an unauthenticated visitor could get a PHP file past the filter.
There’s one meaningful limit on how many sites this exposes: exploitation requires a form that has both a File Upload field and a Select field configured together. A simple two-field contact form without those exact elements isn’t exposed the same way. If you’re running Forminator, the question worth checking isn’t “do I have file upload forms,” it’s “do any of my file upload forms also include a select or dropdown field.”
Why the fix isn’t the end of the story
Patched Forminator (version 1.56.2 and later) closes the specific bypass Wordfence found. But the more useful thing this bug demonstrates is what happens after a malicious file gets past a plugin’s filter, because that’s the part that determines whether the upload is a nuisance or a full compromise.
By default, WordPress upload directories on most properly configured hosts carry `.htaccess` rules (or equivalent server-level configuration on nginx) that prevent PHP files from executing even if one somehow lands there. That server-side rule is a second, independent layer that doesn’t care what plugin let the file through. Forminator’s own default configuration relies on exactly that protection. The scenario where the uploaded PHP file runs is when a site administrator has configured a custom file upload storage root, outside the default protected directory, without replicating the same execution restrictions on the new location. In that specific case, simply requesting the uploaded file’s URL is enough to trigger it.
That distinction matters more than the CVE number does. A plugin-level filter bypass is a bug that gets patched. A missing execution restriction on an upload directory is a configuration gap that persists across every plugin you ever install, current and future, until someone fixes the server config directly.
What upload folder protection looks like on a server
It helps to be concrete about what’s actually sitting between a malicious upload and a working exploit, because “execution restrictions” is easy to nod along to without picturing the mechanism. On Apache-based hosting, the standard approach is a `.htaccess` file placed directly inside `wp-content/uploads/` containing a rule like `php_flag engine off` or a handler removal directive, which tells the server not to process any file in that directory as PHP regardless of its extension. On nginx, which doesn’t read `.htaccess` files at all, the equivalent has to live in the server block configuration itself, typically a `location` block matching the uploads path that refuses to hand `.php` requests to the PHP-FPM handler.
That’s a meaningful practical difference for anyone comparing hosts or migrating between them: an nginx-based host that hasn’t explicitly configured this protection at the server-block level has no `.htaccess` fallback to catch the gap, because nginx simply ignores that file format. If you’ve ever moved a WordPress site from Apache-based shared hosting to an nginx-based VPS and assumed your existing `.htaccess` rules carried over automatically, upload directory execution restrictions are exactly the kind of protection that can silently disappear in that move unless someone rebuilt the equivalent nginx rule.
This is not a Forminator-specific problem
Forminator is the plugin in this particular disclosure, but the pattern of “file upload field plus some secondary field whose value influences upload handling” is common across WordPress form builders generally, and blocklist-based file type filtering has been bypassed before on other plugins using similar tricks: double extensions, null-byte tricks, MIME type confusion, and now pipe-alternative key matching. Treating this as “avoid Forminator” misses the more durable lesson, which is that any plugin’s upload filter is a single point of failure if it’s the only thing standing between a visitor and PHP execution on your server.
Sites running WPForms, Gravity Forms, Contact Form 7 with an upload add-on, or a custom-built upload feature all depend on the same two-layer model: plugin-level file type filtering, and server-level execution restriction on wherever those files land. The plugin layer gets patched reactively, after someone finds the bypass. The server layer, done correctly once, protects you regardless of which plugin fails next. A site that has never run Forminator and never will is not exempt from this lesson; it just hasn’t had its own version of this disclosure yet.
What to check on your own site
If you run Forminator, updating to 1.56.2 or later closes this specific hole and should happen without waiting for a maintenance window; Wordfence and the plugin’s own changelog both confirm the patch. But regardless of which form plugin you’re running, three checks are worth doing once and then leaving alone:
1. Confirm your uploads directory (`wp-content/uploads/`, and any custom upload path a plugin has been configured to use) has execution restrictions in place. On Apache-based hosting this is a `.htaccess` file inside the uploads directory itself; on nginx it’s a location block in the server configuration, as described above. If you didn’t set this up deliberately, ask your host whether it’s part of their default WordPress environment.
2. List every form on your site that combines a file upload field with any other dynamic field (select, radio, conditional logic), since that combination is what made the Forminator bug exploitable, independent of the specific plugin involved.
3. If you’ve ever configured a custom storage location for uploaded files, whether through a plugin setting or a media offload integration, verify that location carries the same execution restrictions as the default uploads folder. Custom storage roots are exactly where this class of bug tends to bite, because they’re set up once for a different reason (organization, CDN integration, backup convenience) and rarely revisited from a security angle.
Why the patch window matters more than the current lack of exploitation
No active exploitation of CVE-2026-15748 has been reported as of this writing, which is worth keeping in perspective rather than treating as reassurance. Proof-of-concept exploit code for high-severity WordPress plugin bugs typically follows public disclosure within days, and mass-scanning for unpatched installs tends to start well before most site owners get around to updating. A 9.8-severity, unauthenticated remote code execution bug on a plugin installed on hundreds of thousands of sites is precisely the profile that automated scanning tools get built for quickly; the gap between “a patch exists” and “attackers are actively probing for sites that haven’t applied it” is usually measured in days, not months, and it’s the sites that patch on their own schedule rather than promptly that end up in that window.
For managed WordPress hosting, execution restrictions on upload directories are exactly the kind of server-level configuration that shouldn’t depend on every customer knowing to set it up themselves. If you’re evaluating a host, or checking your current one, asking directly whether PHP execution is disabled by default inside the WordPress uploads directory is a more useful question than asking which specific plugins they scan for. The plugin vulnerability will always be next week’s news, with a different plugin name attached. The server configuration underneath it is the part that determines how much any single plugin bug can actually cost you when it’s your turn.

