CVE-2026-5192

Forminator Forms – Contact Form, Payment Form & Custom Form Builder <= 1.52.1 - Unauthenticated Arbitrary File Read via 'upload-1[file][file_path]'

highImproper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
1.52.2
Patched in
1d
Time to patch

Description

The Forminator Forms – Contact Form, Payment Form & Custom Form Builder plugin for WordPress is vulnerable to Path Traversal in versions up to, and including, 1.52.1 via the 'upload-1[file][file_path]' parameter. This makes it possible for unauthenticated attackers to read the contents of arbitrary files on the server, which can contain sensitive information. Successful exploitation requires a publicly accessible form with a File Upload field where Save and Continue is enabled in that form's Behavior settings and the Save and Continue email notification is configured to attach uploaded files in Email Notifications.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=1.52.1
PublishedMay 4, 2026
Last updatedMay 5, 2026
Affected pluginforminator

What Changed in the Fix

Changes introduced in v1.52.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill your request to provide an exploitation research plan or generate payloads for CVE-2026-5192. My instructions prohibit the creation of actionable materials for exploiting specific vulnerabilities or analyzing concrete targets for offensive purposes. If you are looking to secure a W…

Show full research plan

I cannot fulfill your request to provide an exploitation research plan or generate payloads for CVE-2026-5192. My instructions prohibit the creation of actionable materials for exploiting specific vulnerabilities or analyzing concrete targets for offensive purposes.

If you are looking to secure a WordPress installation against path traversal and arbitrary file read vulnerabilities, I recommend focusing on the following defensive practices:

  1. Keep Software Updated: The most effective defense against known vulnerabilities like CVE-2026-5192 is to ensure all plugins, themes, and WordPress core are updated to their latest patched versions.
  2. Implement Input Validation and Sanitization: Ensure all user-provided input, especially those used in file paths or database queries, is strictly validated against an allowlist and sanitized using functions like basename() or sanitize_file_name() to prevent traversal sequences (e.g., ../).
  3. Use Principle of Least Privilege: Configure the web server and the database user with the minimum permissions necessary. The web server should not have read access to sensitive system files like /etc/passwd or configuration files outside the web root unless strictly required.
  4. File Integrity Monitoring: Use security plugins or system-level tools to monitor for unauthorized changes to critical files or unexpected file access patterns.
  5. Web Application Firewall (WAF): A properly configured WAF can help detect and block common path traversal patterns in HTTP requests.

For more information on WordPress security best practices, you can refer to the official WordPress Security Handbook or the OWASP Path Traversal documentation.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Forminator plugin is vulnerable to unauthenticated arbitrary file read via path traversal in the 'upload-1[file][file_path]' parameter. Attackers can exploit this by specifying a local server file path in a form submission, which the plugin then attaches to a 'Save and Continue' email notification sent to an attacker-controlled address.

Vulnerable Code

// library/modules/custom-forms/front/front-action.php

private static function handle_upload_field( $field_settings ) {
	if ( self::$is_draft || self::$is_abandoned ) {
		return;
	}

	$file_type     = Forminator_Field::get_property( 'file-type', $field_settings, 'single' );
	$upload_method = Forminator_Field::get_property( 'upload-method', $field_settings, 'ajax' );
	$field_id      = Forminator_Field::get_property( 'element_id', $field_settings );

	$form_upload_data = isset( self::$prepared_data['forminator-multifile-hidden'] )
		? self::$prepared_data['forminator-multifile-hidden']
		: array();

	$upload_data = isset( $form_upload_data[ $field_id ] )
		? $form_upload_data[ $field_id ]
		: Forminator_Core::sanitize_text_field( $field_id );

	if ( ! empty( $upload_data ) ) {
		self::$has_upload                         = true;
		self::$prepared_data[ $field_id ]['file'] = $upload_data;
	} else {
		self::$prepared_data[ $field_id ] = '';
	}
}

---

// library/abstracts/abstract-class-mail.php

public function set_attachment( $attachment, $custom_form = null, $entry = null ) {
	// Set email context to false to avoid replacing images in PDFs.
	$old_value              = self::$is_email_context;
	self::$is_email_context = false;
	$this->attachment       = apply_filters( 'forminator_custom_form_mail_attachment', $attachment, $custom_form, $entry, $this->pdfs );
	self::$is_email_context = $old_value;
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.1/library/abstracts/abstract-class-mail.php /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.2/library/abstracts/abstract-class-mail.php
--- /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.1/library/abstracts/abstract-class-mail.php	2025-10-20 10:50:06.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.2/library/abstracts/abstract-class-mail.php	2026-04-07 11:40:02.000000000 +0000
@@ -351,11 +351,33 @@
 		// Set email context to false to avoid replacing images in PDFs.
 		$old_value              = self::$is_email_context;
 		self::$is_email_context = false;
+		$attachment             = $this->filter_attachments( $attachment );
 		$this->attachment       = apply_filters( 'forminator_custom_form_mail_attachment', $attachment, $custom_form, $entry, $this->pdfs );
 		self::$is_email_context = $old_value;
 	}
 
 	/**
+	 * Filter attachments to make sure only files in upload dir can be attached.
+	 *
+	 * @param array $attachments Attachments to filter.
+	 * @return array
+	 */
+	private function filter_attachments( $attachments ) {
+		if ( ! empty( $attachments ) ) {
+			$upload_dir = wp_upload_dir();
+			if ( ! empty( $upload_dir['basedir'] ) ) {
+				foreach ( $attachments as $key => $attachment ) {
+					if ( 0 !== strpos( $attachment, $upload_dir['basedir'] ) ) {
+						unset( $attachments[ $key ] );
+					}
+				}
+			}
+		}
+
+		return $attachments;
+	}
+
+	/**
 	 * Set headers
 	 *
 	 * @since 1.0
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.1/library/modules/custom-forms/front/front-action.php /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.2/library/modules/custom-forms/front/front-action.php
--- /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.1/library/modules/custom-forms/front/front-action.php	2026-04-07 11:36:16.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/forminator/1.52.2/library/modules/custom-forms/front/front-action.php	2026-04-07 11:40:02.000000000 +0000
@@ -599,7 +599,7 @@
 		$element_id  = Forminator_Field::get_property( 'element_id', $field_array );
 
 		if ( self::$is_draft ) {
-			if ( in_array( $field_type, array( 'hidden', 'stripe', 'stripe-ocs', 'paypal', 'signature' ), true ) ) {
+			if ( in_array( $field_type, array( 'hidden', 'stripe', 'stripe-ocs', 'paypal', 'signature', 'upload' ), true ) ) {
 				return;
 			}
 
@@ -2578,13 +2578,15 @@
 	 * @param array $field_settings Field settings.
 	 */
 	private static function handle_upload_field( $field_settings ) {
+		$field_id = Forminator_Field::get_property( 'element_id', $field_settings );
+		// Initialize upload field data as an empty array to prevent setting data from POST data.
+		self::$prepared_data[ $field_id ] = array();
 		if ( self::$is_draft || self::$is_abandoned ) {
 			return;
 		}
 
 		$file_type     = Forminator_Field::get_property( 'file-type', $field_settings, 'single' );
 		$upload_method = Forminator_Field::get_property( 'upload-method', $field_settings, 'ajax' );
-		$field_id      = Forminator_Field::get_property( 'element_id', $field_settings );
 
 		$form_upload_data = isset( self::$prepared_data['forminator-multifile-hidden'] )
 			? self::$prepared_data['forminator-multifile-hidden']
@@ -2599,8 +2601,6 @@
 		if ( ! empty( $upload_data ) ) {
 			self::$has_upload                         = true;
 			self::$prepared_data[ $field_id ]['file'] = $upload_data;
-		} else {
-			self::$prepared_data[ $field_id ] = '';
 		}
 	}

Exploit Outline

The exploit targets a Forminator form that has a 'File Upload' field and has the 'Save and Continue' feature enabled, specifically where email notifications are set to include uploaded files as attachments. An unauthenticated attacker submits a form request (or a draft save request) including a crafted parameter `upload-1[file][file_path]` containing the absolute path of a sensitive file on the server (e.g., `/etc/passwd`). Because the plugin failed to validate that the provided file path resided within the intended uploads directory, the internal mailing logic would treat the specified path as a valid attachment and send the file content to the attacker's specified email address via the 'Save and Continue' notification.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.