CVE-2026-14894: Super Forms wp_ajax_nopriv Upload Flaw
By WP Vanguard Team
CVE-2026-14894 carries a CVSS score of 9.8, and it doesn't need a stolen password, a phished admin, or a chained exploit to work. The Super Forms - Drag & Drop Form Builder plugin, running on WordPress sites up to and including version 6.3.313, let an unauthenticated visitor upload a file straight through its submit_form AJAX handler. The vendor, WebRehab, shipped a fix in 6.3.314. The flaw was disclosed on July 9, 2026.
What makes this one worth a closer look isn't the file upload itself. Unauthenticated file upload bugs show up constantly; we've covered a near-identical class of bug in the Ninja Forms File Upload vulnerability before. What's instructive here is why the check that was supposed to stop it didn't. The plugin had a nonce check on the upload handler. It just wasn't checking the right thing, because a nonce was never designed to answer the question the developer was asking it.
How the flaw works
Super Forms registers submit_form as a wp_ajax_nopriv_submit_form handler, meaning it's explicitly reachable by logged-out visitors, which is correct: public-facing forms need to accept submissions from people who've never logged in. The handler processes a data parameter that can carry a datauristring value, essentially a base64-encoded file embedded in the request. That's the arbitrary file upload vector, and the researchers who reported it found two separate failures stacked together. The bug is tracked under CWE-434, "Unrestricted Upload of File with Dangerous Type," a classification that shows up constantly in WordPress plugins because file uploads are one of the few places a plugin has to write attacker-controlled bytes to disk.
First, there was no file type validation against the uploaded content. The handler didn't check the actual bytes or restrict extensions to a safe allowlist before writing the file to disk. Second, and more interesting, there was no capability check at all on who was permitted to call this handler and upload something.
The plugin's only gate was a session nonce. That would matter if the nonce were hard to get. It wasn't. A separate nopriv AJAX action existed specifically to mint a fresh nonce for any visitor who asked for one, no login, no prior session state, nothing. An attacker's script sent one request to grab a valid nonce, then a second request to submit_form carrying that nonce and a malicious file payload. Two HTTP calls, no authentication, arbitrary file write. Given that WordPress uploads directories are frequently web-accessible and PHP is often still executable there depending on server config, "arbitrary file" quickly becomes "arbitrary code."
Notice what didn't have to happen for this to work. No password guessing, no session hijacking, no social engineering a site owner into clicking a link. The two requests an attacker needs are the same two requests a legitimate form submission would make, just aimed at a different target. That's what separates a flaw like this from most of the vulnerability classes in our rundown of how WordPress sites actually get hacked: there's no human in the loop to fool, only a missing server-side check to walk past.
Who is affected
Every site running Super Forms - Drag & Drop Form Builder at version 6.3.313 or earlier is affected, regardless of configuration. The submit_form handler is registered as nopriv by design, since the plugin's whole purpose is accepting form submissions from site visitors, so there's no setting that turns this exposure off. If your site has the plugin active and public-facing forms enabled, which is the plugin's default use case, you were reachable. Update to 6.3.314 or later closes the hole.
There's no privilege prerequisite here worth listing, which is what pushes the CVSS score to 9.8 in the first place. No subscriber account, no contributor role, no admin session to steal first. A scanner that already knows the submit_form action name and the shape of the super_create_nonce request can walk the two-step sequence against any site running the plugin, which is exactly the kind of vulnerability that gets folded into mass automated scanning within days of public disclosure.
A nonce is not a lock
This is the part worth sitting with, because it's the single most common misconception we see in plugin security reviews, and it's not unique to Super Forms.
A nonce answers one question: did this request originate from a page my server rendered, for this specific action, recently? That's it. It proves intent and origin, which is exactly what you need to stop cross-site request forgery, where a malicious site tricks a logged-in visitor's browser into firing a request they never meant to send. We've written a full explainer on what WordPress nonces protect and what they don't, and the Super Forms bug is close to a textbook illustration of the pattern described there.
What a nonce cannot tell you is whether the caller is allowed to do the thing they're asking for. Those are two different problems with two different fixes: authentication asks who you are, authorization asks what you're permitted to do, and CSRF protection asks whether this specific request was actually intended by that person, right now. A nonce only ever answers the third question. When a plugin treats a passing nonce check as proof the request is legitimate in every sense, it's collapsing three separate security properties into one, and the two it dropped are usually the ones that actually stop an attacker.
The design failure gets worse once you notice where the nonce came from. Nonces are meant to be unpredictable to anyone who didn't load the page that generated them. Super Forms handed its nonce out through a second public endpoint built for that exact purpose. At that point the token isn't proving anything about the request's origin; it's just a value both sides happen to know, no different from a hardcoded string. The lock was real, but the key was sitting in a bowl by the front door.
The difference between the two approaches is small in terms of lines of code and large in terms of consequences:
// Nonce-only: proves origin, proves nothing about permission or content
add_action( 'wp_ajax_nopriv_submit_form', function () {
check_ajax_referer( 'sf_nonce', 'nonce' );
handle_upload( $_POST['data'] ); // no type check, no allowlist
} );
// Nonce plus actual validation of the request itself
add_action( 'wp_ajax_nopriv_submit_form', function () {
check_ajax_referer( 'sf_nonce', 'nonce' );
$type = wp_check_filetype( $_POST['filename'] )['type'];
if ( ! in_array( $type, ALLOWED_UPLOAD_TYPES, true ) ) {
wp_send_json_error( 'Unsupported file type', 400 );
}
handle_upload( $_POST['data'] );
} );
The nonce line is identical in both. What separates a safe nopriv handler from a critical CVE is everything after it.
The underlying lesson generalizes past this one plugin. Registering a wp_ajax_nopriv_ handler is an explicit decision to serve logged-out traffic, and WordPress's own developer documentation frames it exactly that way: the nopriv variant exists specifically for endpoints that must work without a session. That decision doesn't relax your validation requirements, it multiplies them. Every input needs the scrutiny you'd give a form submitted by a stranger from an unknown machine, because that's precisely what it is. File type validation against actual content, not just a nonce, is the bar for any handler that accepts uploads from the public internet, logged in or not.
What to do now
Check your Super Forms version. Anything at 6.3.313 or below needs to move to 6.3.314 or later immediately; there's no partial mitigation or config workaround since the handler is nopriv by design. If your site was running an affected version with public forms live, treat this as a potential compromise, not just a patch-and-move-on situation.
Check your uploads directory for files you don't recognize, particularly anything with a .php, .phtml, .php5, or double extension pattern (.jpg.php) sitting alongside your legitimate form attachments. Look at file modification timestamps around and after July 9, 2026, if your site was running a vulnerable version during that window. If you find anything unexpected, don't just delete it: a webshell dropped through this path is exactly the kind of persistence mechanism we cover in our guide to PHP backdoors in WordPress, and attackers who got in once often leave more than one way back in.
Review your server's PHP execution settings for the uploads directory while you're in there. Disabling PHP execution in wp-content/uploads/ doesn't fix this vulnerability class, but it does mean a successful arbitrary upload can't be immediately weaponized into remote code execution, which is a reasonable defense-in-depth step regardless of which plugin triggered the concern. It's a five-minute change, and it stays useful against the next unpatched upload handler too, whichever plugin ships it.
WP Vanguard flags nopriv AJAX handlers that accept file uploads without corresponding validation checks as part of its plugin scan, which is the class of bug this CVE falls into.
References
- Wordfence: Super Forms <= 6.3.313 - Unauthenticated Arbitrary File Upload via data Parameter (datauristring) Value
- NVD: CVE-2026-14894 Detail
- Patchstack: Super Forms - Drag & Drop Form Builder <= 6.3.313 - Unauthenticated Arbitrary File Upload
- WordPress Developer Reference: wp_ajax_nopriv_(action) hook
Related reading
Check Your WordPress Site Security
Free scan, no login required. Find vulnerabilities before attackers do.
Scan Your Site FreeGet weekly WordPress security tips
Vulnerability alerts, plugin updates, and security guides. No spam. Unsubscribe any time.