MW WP Form CVE-2026-5436: Brief Summary of an Unauthenticated Arbitrary File Move Vulnerability Affecting 200,000 WordPress Sites

A brief summary of CVE-2026-5436, a high severity arbitrary file move vulnerability in the MW WP Form WordPress plugin (versions 5.1.1 and earlier) that allows unauthenticated attackers to relocate critical files like wp-config.php. Includes patch details, detection strategies, and vendor security history.

CVE Analysis

10 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-04-08

MW WP Form CVE-2026-5436: Brief Summary of an Unauthenticated Arbitrary File Move Vulnerability Affecting 200,000 WordPress Sites
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

An unauthenticated path traversal flaw in the MW WP Form WordPress plugin allows attackers to move arbitrary files on the server, including critical configuration files like wp-config.php, into the public uploads directory. With roughly 200,000 active installations exposed and no authentication required, this vulnerability represents a significant risk to the WordPress ecosystem.

MW WP Form is a popular contact form builder plugin for WordPress, developed by web soudan and inc2734. It is widely used across Japanese and international WordPress deployments, offering form creation with file upload capabilities and database storage of inquiry data. Its large install base and deep integration with WordPress file handling make vulnerabilities in this plugin particularly impactful.

Technical Information

Root Cause: path_join() and Unsanitized Upload Field Keys

The vulnerability (classified as CWE-22, Path Traversal) stems from a fundamental misunderstanding of how WordPress's path_join() function behaves. When path_join() receives an absolute path as its second argument, it returns that absolute path unchanged, completely discarding the first argument (the intended base directory). The MW WP Form plugin relied on path_join() to constrain file operations within a designated upload directory, but never validated that the input to path_join() was actually a relative path.

Specifically, the generate_user_file_dirpath() function in classes/models/class.directory.php accepts a $name parameter (the upload field key) and passes it directly to path_join() alongside the intended user directory. If $name is an absolute path like /var/www/html/wordpress/wp-config.php, the function returns that absolute path verbatim.

Attack Flow

The exploitation follows a clear sequence through the plugin's data model and file handling pipeline:

Step 1: Injection via POST parameter. The attacker submits a crafted POST request to a form that uses MW WP Form. The mwf_upload_files[] parameter contains an absolute filesystem path (e.g., /var/www/html/wordpress/wp-config.php) as a key value. No authentication is required.

Step 2: Data model ingestion. The plugin's Data model loads the submitted parameters via the _set_request_valiables() function. The attacker controlled key enters the plugin's internal data structures without sanitization.

Step 3: Key iteration and path resolution. During form processing, regenerate_upload_file_keys() in class.data.php iterates over the upload file keys and calls generate_user_filepath() with the attacker supplied key as the $name argument. The key survives validation because the targeted file genuinely exists at the specified absolute path.

Step 4: File relocation. The _get_attachments() method re reads the surviving keys and passes the resolved absolute file path to move_temp_file_to_upload_dir(). This function calls PHP's rename(), which physically moves the targeted file from its original location into the WordPress uploads folder.

Why the Previous Fix (5.1.1) Was Insufficient

This vulnerability is notable because it bypasses the fix introduced in version 5.1.1 for the related CVE-2026-4347. That earlier patch hardened the generate_user_filepath() function, but the attacker controlled upload field key still flowed unchecked into generate_user_file_dirpath(). The regenerate_upload_file_keys() function in class.data.php iterated over these keys without proper sanitization, meaning the 5.1.1 path traversal mitigations could be bypassed through this alternative code path.

Exploitation Preconditions

Two conditions must be met for successful exploitation:

  1. A file upload field must be actively present on the targeted form.
  2. The "Saving inquiry data in database" option must be enabled for that form.

If either condition is absent, the vulnerable code path is not reachable.

Patch Information

A public patch is available in MW WP Form version 5.1.2, released on April 8, 2026. The fix was merged via Pull Request #32 from the security/fix-file-upload-path-validation branch, authored by Kazuto Takeshita, in commit f872ab18ca670f5867b2241745daa30cd0fab861. The commit touches seven files with 203 additions and 20 deletions, with the security critical logic concentrated in classes/models/class.directory.php.

Defense in Depth: Three New Validation Methods

The 5.1.2 patch introduces three new protected static methods in class.directory.php:

_is_valid_path_segment($value) acts as a strict gatekeeper, rejecting any path component that is empty, contains null bytes (\0), equals . or .., is an absolute path, or does not match its own wp_basename() (meaning it contains directory separators). This validation is now applied to both the $name and $filename parameters before they can influence any file system path.

_is_within_expected_dir_candidate($form_id, $path) independently reconstructs what the legitimate user temp directory should be and verifies the candidate path either matches it exactly or begins with it (plus a trailing slash). This is the critical containment check that defeats the path_join() absolute path bypass.

_get_expected_user_dir($form_id, $base_dir) independently computes the expected user directory from the CSRF token (validated against /^[a-z0-9]+$/) and the form ID (validated against /^\d+$/), returning false if any component is malformed.

Patched generate_user_file_dirpath()

Here is the core validation logic added to the previously unprotected function:

public static function generate_user_file_dirpath( $form_id, $name ) { if ( ! static::_is_valid_path_segment( $name ) ) { throw new \RuntimeException( '[MW WP Form] Invalid file reference requested.' ); } $user_dir = static::generate_user_dirpath( $form_id ); $user_file_dir = path_join( $user_dir, $name ); if ( ! static::_is_within_expected_dir_candidate( $form_id, $user_file_dir ) ) { throw new \RuntimeException( '[MW WP Form] Invalid file reference requested.' ); } return $user_file_dir; }

Patched generate_user_filepath()

The old inline check (wp_basename($normalized_filename) !== $normalized_filename || strstr($normalized_filename, "\0")) was replaced with the segment validator up front and the containment check after path assembly:

if ( ! static::_is_valid_path_segment( $filename ) ) { throw new \RuntimeException( '[MW WP Form] Invalid file reference requested.' ); } // ... path assembled ... if ( ! static::_is_within_expected_dir_candidate( $form_id, $filepath ) ) { throw new \RuntimeException( '[MW WP Form] Invalid file reference requested.' ); }

Additionally, generate_user_dirpath() gained a numeric only form ID check:

if ( ! preg_match( '/^\d+$/', (string) $form_id ) ) { throw new \RuntimeException( '[MW WP Form] Invalid form ID.' ); }

Caller Side Error Handling

Both regenerate_upload_file_keys() in class.data.php and _get_attachments() in class.main.php were updated to wrap calls to generate_user_filepath() in try/catch blocks. When a RuntimeException is caught (indicating a path traversal attempt), the code logs the error, removes the offending upload key from the list, clears its value, and continues processing the remaining legitimate keys. This ensures that a single malicious entry does not crash the entire form submission.

The commit also includes comprehensive unit tests in test-directory.php and test-data.php covering absolute paths, nested paths, directory traversal sequences like ../../../wordpress, and Windows style absolute paths.

Detection Methods

Web Server Access Log Analysis

The most direct detection method targets the attack's entry point: the mwf_upload_files[] POST parameter. Defenders should review web server access logs (Apache, Nginx, or a reverse proxy) for POST requests to any MW WP Form endpoint where the request body includes mwf_upload_files keys containing absolute filesystem paths or path traversal sequences (e.g., ../). Because the vulnerability requires no authentication, any external IP making such requests is suspect. Web Application Firewalls (WAFs) can be configured to inspect POST body parameters for the mwf_upload_files key combined with values that begin with / or contain traversal patterns like ...

PHP Error Log Monitoring (Post Patch)

If you have already applied the patch (version 5.1.2), the fix itself provides a built in detection mechanism. The patched code calls error_log() with the message from a RuntimeException whenever an invalid path segment is detected. Exploitation attempts against a patched instance will produce error log entries containing the string [MW WP Form] Invalid file reference requested. in the PHP error log. Multiple occurrences from the same source IP should be treated as high confidence indicators of targeted attack activity.

File System Integrity Monitoring

The exploit uses PHP's rename() to move a targeted file (not copy it) into the WordPress uploads directory. This means a successful exploitation produces two simultaneous filesystem anomalies: (1) a critical file such as wp-config.php disappears from its expected location, and (2) that same file appears unexpectedly inside the wp-content/uploads/ directory tree. File Integrity Monitoring (FIM) tools such as OSSEC, Wazuh, or Tripwire should be configured to alert on any deletion or modification of wp-config.php and other sensitive WordPress core files. Additionally, monitoring the uploads directory for non media files (e.g., .php, .conf, .ini files) can catch post exploitation artifacts.

Behavioral and Host Based Indicators

A successful exploitation will almost certainly cause an immediate observable side effect: if wp-config.php is moved, the WordPress site will display Error establishing a database connection because the application can no longer locate its configuration. A sudden appearance of this error on a previously functional site running MW WP Form should be investigated for this CVE. Uptime monitoring and synthetic health checks on WordPress instances running MW WP Form can serve as a fast response detection layer.

Vulnerability Scanning and Version Detection

Standard vulnerability scanners (Nessus, Qualys, OpenVAS) and WordPress specific tools like WPScan or Wordfence can identify vulnerable installations by checking the MW WP Form plugin version. Any installation running version 5.1.1 or earlier is affected.

Note on Public Signatures

As of publication, no vendor agnostic IDS/IPS rules (Snort, Suricata), Sigma rules, or YARA rules explicitly targeting CVE-2026-5436 have been identified in public repositories. The detection strategies above, particularly log monitoring for the mwf_upload_files[] parameter with path like values, PHP error log alerting, and FIM on critical WordPress files, remain the most actionable approaches at this time.

Affected Systems and Versions

All versions of the MW WP Form plugin for WordPress up to and including version 5.1.1 are affected. The vulnerability is only exploitable on installations where both of the following conditions are true:

  1. A file upload field is present on at least one active form.
  2. The "Saving inquiry data in database" option is enabled for that form.

The fix is available in version 5.1.2 and later.

Vendor Security History

The MW WP Form plugin has a documented pattern of severe file handling vulnerabilities across consecutive releases, all exploitable without authentication:

Plugin Version RangeVulnerability TypeCVE
Versions 5.0.1 and earlierUnauthenticated Arbitrary File UploadRelated prior CVE
Versions 5.1.0 and earlierUnauthenticated Arbitrary File Move via move_temp_file_to_upload_dirRelated prior CVE
Versions 5.1.1 and earlierUnauthenticated Arbitrary File Move and Read via regenerate_upload_file_keysCVE-2026-5436

The recurring nature of these file manipulation flaws, all centered on insufficient input validation in file system operations, suggests systemic architectural weaknesses in the plugin's file handling code. Organizations using this plugin should apply elevated scrutiny to future updates and consider implementing strict WAF rules for all form submissions as an additional layer of defense.

References

Detect & fix
what others miss

Security magnifying glass visualization