- What broke. Two loops in Elementor Pro’s file upload field disagree about what an empty file is. That gap lets an unauthenticated visitor write a PHP file into a public folder and run it.
- Who is affected. Sites on 4.2.1 or below with a published page whose Elementor form has a File Upload field. Having Elementor Pro installed is not enough on its own.
- What we did. Blocked execution from that upload path across the entire hosting fleet in under two hours, then swept every affected site for signs of earlier compromise. All clean.
- What you do. Update to Elementor Pro 4.2.2 when it suits you. If you host with us, there is nothing urgent on your side.
A critical flaw in Elementor Pro lets anyone on the internet upload a PHP file to a vulnerable site and then execute it. No login, no nonce, no account. The bug sits in the Forms module, where the code that checks a file’s extension and the code that moves that file into place walk the same data under different rules. Elementor closed it in 4.2.2 on 19 August 2026.
The vulnerability was found and reported by Tin Pham (TF1T) through the Patchstack Bug Bounty Program. The technical analysis below builds on Patchstack’s advisory, which is worth reading in full.
What the vulnerability is
Elementor Pro’s Forms module lets you drop a File Upload field into any form, so visitors can attach a document. To keep that safe, the field checks every uploaded file’s extension against an allowed list and a blocklist, and the blocklist covers .php and every other executable type.
That check is sound. It simply never runs.
The extension check and the step that actually moves the file into place are two separate loops over the same submitted data. They disagree about what to do with an empty file entry, an upload part with a blank filename. Submit two file parts for one field and that disagreement lets the second one walk straight past the blocklist.
The result is a .php file sitting in a publicly reachable uploads directory. Request it in a browser and the server runs it. Two details make that serious:
- No authentication and no nonce. The vulnerable form is a public contact form by design, so anyone on the internet can reach it.
- Every version ever shipped is affected. The vulnerable range runs from the first release up to 4.2.1, so the flaw sat there for years.
The root cause: two loops, two different rules
The File Upload field lives in modules/forms/fields/upload.php. When a form is submitted, validation() walks the submitted file entries and type-checks each one. Separately, process_field() walks the same entries and moves each upload into the public forms directory.
Here is the validator. Watch what it does when it meets an empty entry:
foreach ( $files[ $id ] as $index => $file ) { // an upload part with a blank filename if ( ! $field['required'] && UPLOAD_ERR_NO_FILE === $file['error'] ) { return; // <-- leaves the WHOLE method. Every later entry goes unchecked. } // the extension blocklist lives here, and never gets reached if ( ! $this->is_file_type_valid( $field, $file ) ) { $ajax_handler->add_error( $id, 'This file type is not allowed.' ); } }
Now the mover, walking the exact same array:
foreach ( $files[ $id ] as $index => $file ) { if ( UPLOAD_ERR_NO_FILE === $file['error'] ) { continue; // <-- skips only THIS entry. The loop carries on to the next one. } // ... the file is moved into wp-content/uploads/elementor/forms/ }
One keyword apart. return abandons the method; continue skips a single entry. So an empty first part makes the validator stop reading before it ever sees the .php part behind it, while the mover shrugs past the same empty part and writes the .php file anyway. The validator reports a clean submission because it stopped looking. The mover proceeds because it did not.
The plugin renames uploads, so the attacker still has to work out what the stored file is called. That step is cheap, and Patchstack documents it. We are not repeating the method here.
The attack, start to finish
Who is actually affected
This is the part most coverage gets wrong, so we will be precise. Having Elementor Pro installed is not by itself enough to be exploitable. The attack needs a door, and the door is a form. To be at risk, a site needs a published page carrying an Elementor Form widget that includes a File Upload field.
Plenty of Elementor Pro sites never touch the Forms module, or use it without file uploads. Those sites run vulnerable code with no reachable entry point for this particular attack.
Do not read that as comfort, though. It is an everyday configuration: job applications, “attach a photo or a receipt”, support tickets with a screenshot. And the field’s Required toggle is off by default, so nothing unusual has to be switched on.
One piece of good news on timing: at the point of disclosure there was no public proof of concept and no known exploitation in the wild. Nobody was spraying this at the internet yet.
Why your host probably cannot fix this for you
Here is the awkward structural problem with this disclosure, and it is not a dig at anyone.
Elementor Pro is a licensed commercial plugin. Updates are pulled with the customer’s own licence key. No host can push 4.2.2 onto a customer’s site on their behalf, however much it would like to. We cannot either.
So on most hosting the clock runs like this: the advisory goes public, and the site stays exposed until its owner personally logs in, notices, and clicks update. That might be an hour. On a client brochure site nobody has opened in eight months, it might be never.
The plugin update is the repair. The only question that matters is what holds the line in the gap before the customer gets to it.
What we did
If your sites run on InstaWP, this one was handled for you. Here is what that actually looked like on the night.
Under two hours from a public advisory to fleet-wide protection, with a forensic sweep behind it.
The logic of the block is simple. The upload is only the setup. The exploit pays off at the moment the uploaded file is executed. So we deny execution from that upload path. A malicious file has nowhere useful to land and nothing to run when it gets there.
Three properties of that approach matter:
- It sits underneath the plugin, not inside it. The protection does not care which Elementor Pro version a site runs. It held before customers updated, and it still holds afterwards.
- It changed nothing in your site. No customer files touched, no forced plugin update, no version decisions made on your behalf.
- Real uploads kept working. We verified site by site afterwards that genuine form attachments, PDFs, images, documents, still went through. Safety did not get traded for a broken careers page.
Blocking new attempts is only half the job. The vulnerable range covers every version Elementor Pro has ever shipped, so we could not assume we were early. Someone could have found this years before Patchstack published. So we ran a forensic sweep of every affected site on the platform, looking for evidence it had already been used against us. Every one came back clean.
We are deliberately not publishing the rule itself. A copy-pasteable block tells an attacker exactly what shape to route around, which helps them more than it helps you. Same call we made during our wp2shell response in July.
What that looks like next to typical hosting
What you should do
If your sites are on InstaWP: update to Elementor Pro 4.2.2 at your convenience. Next time you are in the dashboard is fine. There is no 2am patch window here.
We still want you to update, because a server-level block and a patched plugin are different things. Ours neutralises the attack. The vendor’s release removes the bug. You want both.
If you run Elementor Pro somewhere else: update today, not this week, and start with anything carrying a public form that accepts attachments. Then check the upload directory:
wp-content/uploads/elementor/forms/ for anything that is not a document or image type your forms actually accept, especially files ending in .php. Patchstack recommends the same check, and it is worth five minutes.If you manage sites for clients, the ones to worry about are the quiet ones. The brochure site nobody has logged into since launch is running Elementor Pro from two years ago, and it sits inside the vulnerable range along with everything else.
What this bug actually teaches
Neither loop is wrong on its own. Read either one in isolation and nothing looks alarming. The bug exists only in the gap between them: the code that decides whether an upload is allowed and the code that acts on that upload walk the same data under different rules. One empty file part is enough to make them disagree, and that disagreement turns a restricted upload field into unauthenticated code execution. Whenever a check and the action it guards are written as two separate passes, that gap is where you should look first.
The hosting lesson runs parallel. A licensed plugin puts the patch in the customer’s hands, and the gap between disclosure and that click is where sites get taken. What decides the outcome is whether the platform underneath is watching, and whether it can move across a whole fleet in hours rather than weeks.
If your sites run on InstaWP, this one was handled for you. That is the whole pitch.
References
- Critical unauthenticated file upload to RCE in Elementor Pro (Patchstack): the original advisory and technical writeup.
- CVE-2026-32475 (NVD): the CVE record.
- Elementor Pro changelog: the 4.2.2 release, listed as “Improved code security enforcement in Form widget”.
- Inside our wp2shell response (InstaWP): how we handled the WordPress core RCE in July.