In this article
- Why CF7 keeps showing up in CVE feeds
- CVE-2023-6449 explained without the marketing
- The recurring vulnerability pattern in CF7
- Other CF7 CVEs worth knowing about
- How to tell if your site is affected
- The fix, step by step
- Hardening CF7 beyond just patching
- When to consider an alternative
- Common questions
Why CF7 keeps showing up in CVE feeds
Contact Form 7 is the oldest, most-installed, most-extended contact form plugin in the WordPress ecosystem. That trio of properties is what creates risk:
- Old. It dates from 2007. Some of its architecture predates the modern WordPress hardening conventions for nonces, sanitization, and capability checks.
- Most-installed. Every additional install increases the value of finding a single bug. A working exploit pays out across millions of targets, so attackers spend real time looking.
- Most-extended. Hundreds of "add-on" plugins reach into CF7's internals to add fields, accept payments, save submissions to the database, and upload files. Many of those add-ons inherit CF7's surface area but ship with less hardening than the core plugin.
That last point matters. When we audit a site and flag a CF7-related finding, more than half the time the underlying vulnerability is in a CF7 add-on, not CF7 itself. The CF7 maintainers cannot fix bugs in third-party code, and most site owners are not even aware of which add-ons are installed.
CVE-2023-6449 explained without the marketing
CVE-2023-6449 affects Contact Form 7 versions up to and including 5.8.3. It is an unrestricted-file-upload vulnerability tied to the [file] form-tag, the feature that lets visitors attach a resume, screenshot, or document to a contact form submission.
The mechanics: CF7's filename sanitization logic could be bypassed by including a double extension or a specifically crafted filename. An attacker could submit a file named, for example, cv.pdf.phtml, and under certain server configurations the file would land on disk in the uploads directory with its dangerous extension intact. If the web server was also configured to execute .phtml (or .phar, or .pht) as PHP — which is the default for many shared hosts — the attacker now had remote code execution. From a contact form. Without authentication.
The patch landed in Contact Form 7 5.8.4 on December 14, 2023, and tightened the filename sanitizer to strip every extension after the first one. If you are reading this and you are on 5.8.4 or newer, you are not exposed to this particular CVE.
Quick check
In your WordPress admin, go to Plugins and look at the version next to "Contact Form 7." Anything ≥ 5.8.4 is safe from CVE-2023-6449. Anything older needs to be updated today.
The recurring vulnerability pattern in CF7
If you look at the CF7 CVE history end-to-end, almost every confirmed CVE in the last five years has fallen into one of three buckets:
- File-upload sanitization. The
[file]tag accepts user-provided filenames. Sanitization has been tightened repeatedly. CVE-2020-35489 (unrestricted file upload, fixed in 5.3.2) and CVE-2023-6449 are both in this category. - Reflected XSS via form fields or admin screens. Output that was assumed to be safe (because it came from an admin) turned out to be reachable by an unauthenticated visitor under specific configurations.
- Mail header injection. The
[email]tag and various "From" / "Reply-To" configurations have occasionally allowed an attacker to inject CRLF sequences into outbound mail headers, enabling the site to be used as an open relay for phishing.
The pattern is consistent: anywhere CF7 accepts user input and forwards it somewhere with elevated trust (the filesystem, the mail subsystem, the admin DOM), there is a real risk of a regression. That is not unique to CF7 — it is true of any form plugin — but the install base makes the consequences louder.
Other CF7 CVEs worth knowing about
Two more, beyond CVE-2023-6449, are worth knowing if you maintain older sites:
- CVE-2020-35489 — Unrestricted file upload, fixed in 5.3.2. Severity: critical. If you have a site stuck on a CF7 version older than 5.3.2, treat it as compromised until proven otherwise.
- CVE-2018-9035 — SQL injection in the Contact Form 7 to Database Extension add-on (not CF7 itself). A reminder that the add-on ecosystem is part of your attack surface.
For the canonical, daily-updated list, the WordPress.org plugin page and the WPScan vulnerability database are the right sources. Lockora's CVE feed pulls from both.
How to tell if your site is affected
Step 1: confirm the version
From the admin: Plugins → Installed Plugins → Contact Form 7. From the file system, the version is in /wp-content/plugins/contact-form-7/wp-contact-form-7.php at the top of the file.
Step 2: check whether you actually use file uploads
Most CF7 forms do not use the [file] tag. Open each form in Contact → Contact Forms → [your form] and look for [file ...] in the form template. If no form uses it, the most severe class of CF7 CVEs (file-upload) does not apply to you — though the others still do.
Step 3: look for unexpected files in uploads
If you are on an old CF7 version and you have [file] tags, treat the site as potentially compromised. The relevant directory is usually /wp-content/uploads/wpcf7_uploads/. Look for anything that does not end in an expected document extension: .php, .phtml, .phar, .pht, .htaccess, or any file with a double extension.
Step 4: scan with a security tool
If something looks wrong, do not rely on visual inspection alone. Run a malware scan (Lockora's audit will do this, as will Wordfence or Sucuri). Look specifically for obfuscated PHP and recently-modified files in wp-content/uploads.
The fix, step by step
1. Update Contact Form 7
Plugins → Installed Plugins → Update. If you have automatic plugin updates disabled, this is the moment to reconsider for security plugins like CF7. The current release line as of writing is 5.9.x; anything in that series or later includes the CVE-2023-6449 fix.
2. Block dangerous extensions at the web server
Even after the patch, you want a defense-in-depth layer that refuses to execute anything in /wp-content/uploads/ regardless of what lands there. For Apache, in .htaccess at the uploads root:
<FilesMatch "\.(php|phtml|phar|pht|php3|php4|php5|php7|php8|pl|py|jsp|asp|sh|cgi)$">
Require all denied
</FilesMatch>
For Nginx, in the server block:
location ~* /wp-content/uploads/.*\.(php|phtml|phar|pht|pl|py|jsp|asp|sh|cgi)$ {
deny all;
return 403;
}
This is the single highest-leverage change you can make. It does not just protect against CF7 — it protects against every plugin that ever writes to the uploads directory.
3. Audit CF7 add-ons
Open Plugins → Installed Plugins and look for anything with "Contact Form 7," "CF7," or "Contact Form" in the name beyond CF7 itself. Anything stale — not updated in the last 12 months — should either be updated, replaced, or removed. Pay particular attention to:
- "Contact Form 7 Database" / "CF7 DB" type plugins (submissions storage)
- "Contact Form 7 Multi-Step" type plugins
- Anything that adds payment processing on top of CF7
4. Tighten what file types are accepted
Even with the official patch, you should never accept arbitrary uploads. Constrain the filetypes: attribute on every [file] tag:
[file your-cv filetypes:pdf|doc|docx limit:5mb]
If you only want PDFs, only accept PDFs. The less your form will take, the smaller the attack surface.
Hardening CF7 beyond just patching
- Add a real spam control. CF7 ships with hooks for reCAPTCHA, hCaptcha, Cloudflare Turnstile, and Akismet. Use one. Most malicious-submission CF7 reports we see in audits are from forms with no spam filter at all.
- Move the form URL. The default contact form lives at
/contact/on a lot of sites, which is the first URL automated scanners probe. A custom URL slug will not stop a determined attacker, but it cuts the volume of low-effort scans by 80% or more. - Restrict who can edit forms. By default, anyone with the
edit_pagescapability can edit a CF7 form — including the mail template, which is the most dangerous part. If you only want admins editing forms, use thewpcf7_map_meta_capfilter to requiremanage_options. - Audit your mail template for injection. The "Mail" tab in CF7 lets a form admin reference any field, including user-controlled ones, in the To/From/Reply-To headers. Never put a user-supplied field in a header without sanitization — that is the mail-header-injection vector.
When to consider an alternative
CF7 is fine for most sites if you keep it patched and follow the hardening checklist. But if any of these apply, evaluating an alternative is reasonable:
- You need conditional logic, multi-step forms, file processing, or payments — the things that pull in unmaintained add-ons. Fluent Forms, WS Form, and Gravity Forms have these built in, which removes the add-on attack surface.
- You cannot afford to keep up with monthly plugin updates. A simpler, more modern plugin with a smaller install base may get less attention from scanners.
- You have a regulatory requirement (HIPAA, GDPR Article 32) for documented data handling around form submissions. CF7's default behavior is to email submissions and store nothing — auditable, but spartan.
If you do migrate, do it deliberately: export your forms, recreate them on the new plugin, run both in parallel for a week, then disable CF7 (do not just deactivate — delete, so the code is no longer reachable).
Common questions
Is Contact Form 7 still safe to use?
Yes, on a current version with the hardening above. The plugin is actively maintained, the response time on disclosed CVEs is good, and the maintainer (Takayuki Miyoshi) has been doing this for almost two decades.
Will updating CF7 break my existing forms?
Almost never. CF7 has a strong record of backwards compatibility within a major version. The risk is in add-ons: if you use one that stopped being maintained years ago, it may break on a current CF7 release. Test on a staging copy first if you depend on add-ons.
How often should I check for CF7 updates?
Daily auto-updates are the right default for security-sensitive plugins. If that scares you, set up a staging environment that auto-updates and a production environment that lags 48 hours behind on a manual rollout.
If I was compromised, what now?
Take the site offline. Restore from a backup you took before the suspected compromise window. Update CF7 and every other plugin. Rotate all admin passwords, all application passwords, and the WordPress secret keys in wp-config.php. Run a malware scan and review every file in wp-content/uploads with a recent modification time. Lockora's audit will surface most of this in one pass.
Audit your CF7 install (and everything else) in three minutes.
Lockora cross-checks every installed plugin against the live CVE feed and flags exactly what needs your attention.