CVE-2026-94589: CF7 Extensions 3.4.5 Uploads PHP Without a Login - Patch 3.4.6

The Situation
NVD published CVE-2026-94589 on 2026-10-10T04:18:19.713Z. Same calendar day Wordfence last-updated the Intelligence record (publicly dated 9 October 2026). The product is the WordPress plugin Extensions For CF7 (extensions-for-cf7) - HasThemes' Contact Form 7 add-on for submission storage, conditional fields, redirects, and a signature field. Affected: all versions through 3.4.5. Patched: 3.4.6.[1][2]
Wordfence / NVD CVSS v3.1 is 9.8 CRITICAL (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H). Privileges required: none. User interaction: none.[1][2]
This is not WordPress core. It is not Contact Form 7 itself. It is one third-party slug that sits next to CF7 on a lot of shared-hosting accounts. CISA KEV catalog 2026.10.08 (1,739 entries, newest add still 8 October) does not list this CVE. Treat it as a fresh unauth-RCE-class plugin, not as a KEV clock.[3]
The plugin's own changelog for 3.4.6 (dated 4 October 2026, WordPress.org last_updated 2026-10-04 6:12am GMT, stable tag 3.4.6) says only: "Security: Hardened file upload handling for the Signature field and form submission storage." The CVE number landed six days later.[4]
WordPress.org plugin API active_installs for this slug is 5000. That is the directory's bucket, not a census of our customers, and it is not "rare enough to skip."[4]
What the bug actually is
NVD, verbatim: the plugin "is vulnerable to Arbitrary File Upload in all versions up to, and including, 3.4.5 via the extcf7_submit function." Cause, also NVD/Wordfence: missing file-extension, MIME-type, and size validation in the signature field's validation_filter(), plus no PHP-execution guards in the upload directory, plus a sanitize_file_name() bypass that NVD describes as converting shell.php- into shell.php. Result, their wording: unauthenticated attackers can upload files that may be executable, "which makes remote code execution possible."[1][2]
Researcher on the Wordfence record: Osman Hussein (Onvio B.V.).[2]
We are not publishing an upload sequence. The NVD reference list already points at the 3.4.5 trac lines (class.cf7-signature.php, class.cf7-extensions.php, class.form-data-store.php) and the 3.4.5→3.4.6 changeset (3727009). That is enough for a host to know which files changed. Do not treat this paragraph as a lab result from us.[1]
RCE is conditional on the web server executing PHP in that upload path. NVD says "may be executable." A vhost that already denies PHP under wp-content/uploads/ (or the plugin's own upload dir) still has an unauthenticated arbitrary-file-write. That is a different ticket than a webshell, and it is still a patch.[1][2]
Hunt the fleet - prove absence
Do not grep for "contact-form-7" and call it done. Core CF7 is a different slug. The vulnerable code is extensions-for-cf7.
# locate the slug (cPanel/CloudLinux homes, Plesk vhosts, generic)
find /home /var/www /srv -path '*/wp-content/plugins/extensions-for-cf7' -type d 2>/dev/null
# version from the plugin header, no PHP bootstrap required
grep -h '^[[:space:]]*\*[[:space:]]*Version:' \
/home/*/public_html/wp-content/plugins/extensions-for-cf7/*.php \
/home/*/public_html/wp-content/plugins/extensions-for-cf7/extensions-for-cf7.php \
2>/dev/null
# per-site, when wp-cli is on the account
wp plugin get extensions-for-cf7 --field=version --skip-plugins --skip-themes
wp plugin update extensions-for-cf7 --skip-plugins --skip-themes
wp plugin get extensions-for-cf7 --field=version --skip-plugins --skip-themes
Anything ≤ 3.4.5 is in range. 3.4.6 is the Wordfence patched version and the current WordPress.org stable tag. Do not stop at "CF7 is updated."[2][4]
If you cannot patch today: deactivate this plugin (wp plugin deactivate extensions-for-cf7), not Contact Form 7. Confirm PHP cannot run in upload directories (LiteSpeed / Apache <FilesMatch> / nginx location ~* /wp-content/uploads/.*\.php). That is a compensating control, not a substitute for 3.4.6.[1][2]
After 3.4.6: look for unexpected PHP under the plugin's upload path and under wp-content/uploads/ dated around the window this plugin was unpatched. We did not produce IOCs. "New .php in uploads" is the operator check, not a signature.
Honesty / What We Could Not Verify
- We did not exploit this. No PoC was run against a lab or a customer vhost.
- Not on CISA KEV as of catalog version 2026.10.08 (count 1739, last
dateAdded2026-10-08). We re-read that JSON this morning. Absence from KEV is not absence of scanners.[3] - RCE is NVD/Wordfence "possible," gated on PHP execution in the upload directory. We did not measure how many default LiteSpeed/cPanel vhosts execute PHP there.[1][2]
- Signature field vs any form. NVD names
extcf7_submitand the signaturevalidation_filter(). We did not prove whether a site with the plugin active but no signature tag on a published form is still reachable. Patch anyway; do not inventory form tags as the ticket close.[1] active_installs: 5000is the WordPress.org API bucket, not 5,000 confirmed live sites, and not our fleet.[4]- Pro add-on (HasThemes lists extra upload features in the Pro comparison) was not assessed. This CVE is the free slug
extensions-for-cf7.[4] - Changelog vs CVE date. Vendor shipped 3.4.6 on 4 Oct with a one-line "Hardened file upload" note; NVD assigned the CVE on 10 Oct. We are not claiming silent-patch malice. We are saying scanners will key off the CVE ID, not the changelog adjective.[1][4]
- This lab did not install Contact Form 7 or this plugin.
What this is not
- Not wp2shell, not CVE-2026-87902 (WordPress core page-template RCE, already KEV, already in the queue).
- Not CVE-2026-97670 (Avada / Fusion Builder ≤ 7.16.1 unauth action-hook invocation, CVSS 9.1, patched 7.16.2, NVD also 10 Oct). Different slug (
fusion-builder). Different impact (Wordfence: unauthdo_actionincluding verifiedwp_scheduled_deleteof trashed content; not this upload bug). Scan it on a separate ticket if you sell Avada.[5][6] - Not CVE-2026-104732 (Advanced IP Blocker ≤ 8.13.13 unauth 2FA bypass, CVSS 9.8, Wordfence patched 8.13.14; current stable 8.13.16 as of 10 Oct 12:39pm GMT). Requires the plugin's 2FA feature and a known
user_id. Different slug (advanced-ip-blocker).[7][8] - Not a cPanel CVE. Yesterday's queue (WP Toolkit, Plesk REST, ProFTPD/BIND KEV) is a different hunt.
Sources
[1] https://nvd.nist.gov/vuln/detail/CVE-2026-94589
[2] https://www.wordfence.com/threat-intel/vulnerabilities/id/fa3193c4-dd3e-4d9e-be42-769c7358beae?source=cve
[3] https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
[4] https://wordpress.org/plugins/extensions-for-cf7/ (plugin API 1.2 version 3.4.6, active_installs 5000, changelog 3.4.6 dated 04 Oct 2026)
[5] https://nvd.nist.gov/vuln/detail/CVE-2026-97670
[6] https://avada.com/blog/version-7-16-2-security-update/
[7] https://nvd.nist.gov/vuln/detail/CVE-2026-104732
[8] https://www.wordfence.com/threat-intel/vulnerabilities/id/d080845b-6814-4b10-a3ab-1f5aa1d09132?source=cve