CVE-2026-6222

Forminator Forms <= 1.51.1 - Missing Authorization to Authenticated (Subscriber+) Sensitive Information Disclosure via 'forminator_action' Parameter

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.52
Patched in
1d
Time to patch

Description

The Forminator Forms plugin for WordPress is vulnerable to Missing Authorization in versions up to and including 1.51.1. This is due to the `processRequest()` method in `Forminator_Admin_Module_Edit_Page` (admin/abstracts/class-admin-module-edit-page.php) dispatching sensitive module-management actions — including export, delete, clone, delete-entries, publish/draft, and bulk variants — after only a nonce check, without ever verifying that the current user holds the `manage_forminator_modules` capability. The nonce used (`forminator_form_request`) is unconditionally embedded in the global `forminatorData` JavaScript object and localized on every Forminator admin page, including Templates and Reports pages accessible to users who explicitly lack module-management permissions. Because `processRequest()` is invoked during the `admin_menu` action hook — which fires before WordPress enforces page-level capability checks — a user whose Forminator role is restricted to Templates or Reports can craft a valid POST request targeting any published module and successfully trigger the vulnerable actions. This makes it possible for authenticated attackers with subscriber-level access (or any custom low-privilege Forminator role) to export the complete internal configuration of arbitrary forms/polls/quizzes (including notification routing, integration credentials, and conditional logic), delete modules, delete all submissions/votes, clone modules, or bulk-change publish/draft status.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.51.1
PublishedMay 6, 2026
Last updatedMay 7, 2026
Affected pluginforminator

What Changed in the Fix

Changes introduced in v1.52

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan targets **CVE-2026-6222**, a missing authorization vulnerability in the Forminator Forms plugin. The vulnerability allows low-privileged users (e.g., Subscribers) who have been granted access to limited Forminator pages (like Reports or Templates) to perform administr…

Show full research plan

This exploitation research plan targets CVE-2026-6222, a missing authorization vulnerability in the Forminator Forms plugin. The vulnerability allows low-privileged users (e.g., Subscribers) who have been granted access to limited Forminator pages (like Reports or Templates) to perform administrative actions on forms, polls, and quizzes.


1. Vulnerability Summary

The vulnerability exists in the Forminator_Admin_Module_Edit_Page class, which serves as the base for the Custom Forms, Polls, and Quizzes management pages.

The init() method of this class (found in admin/abstracts/class-admin-module-edit-page.php) calls processRequest(). This init() method is called during the class constructor. Because these admin page classes are instantiated during the admin_menu hook to register the menu items, the processRequest() logic executes for every administrative request before WordPress performs its standard page-level capability checks.

The processRequest() method dispatches sensitive actions (export, delete, clone, etc.) based on the forminator_action parameter. It verifies a nonce (forminator_form_request), but fails to verify if the user possesses the manage_forminator_modules capability. Since the required nonce is localized in the global forminatorData JavaScript object on all Forminator-related admin pages, a user with access only to "Reports" or "Templates" can retrieve the nonce and use it to manipulate forms.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin.php
  • Target Page Parameter: page (e.g., forminator-cform, forminator-poll, forminator-quiz)
  • Action Parameter: forminator_action
  • ID Parameter: id (the ID of the form/poll/quiz to target)
  • Nonce Parameter: _wpnonce
  • Authentication: Authenticated (Subscriber or any role with limited Forminator access).
  • Precondition: The Forminator "Permissions" settings must be configured to allow the attacker's role access to at least one Forminator menu item (e.g., "Templates" or "Reports").

3. Code Flow

  1. Entry Point: A request is made to an admin page, triggering the admin_menu hook.
  2. Instantiation: Forminator_Admin_CForm_Page (or similar) is instantiated.
  3. Constructor: Forminator_Admin_Page::__construct (in admin/abstracts/class-admin-page.php) calls $this->init().
  4. Vulnerable Method: Forminator_Admin_Module_Edit_Page::init() calls $this->processRequest().
  5. Logic: processRequest():
    • Checks isset( $_POST['forminator_action'] ) or isset( $_GET['forminator_action'] ).
    • Retrieves the nonce from _wpnonce.
    • Calls check_admin_referer( 'forminator_form_request', '_wpnonce' ).
    • Missing Check: No call to current_user_can( 'manage_forminator_modules' ).
    • Sink: Executes actions like export_module(), delete_module(), clone_module(), or delete_entries().

4. Nonce Acquisition Strategy

The nonce is contained within the forminatorData object localized by the plugin.

  1. Access Permitted Page: The attacker logs in and navigates to a Forminator page they are permitted to see (e.g., admin.php?page=forminator-reports).
  2. Extract Nonce: The nonce is stored in the JS object key forminator_form_request.
  3. Tool Command:
    // Via browser_eval
    browser_eval("window.forminatorData?.forminator_form_request")
    

5. Exploitation Strategy

Scenario: Sensitive Information Disclosure (Form Export)

The most severe impact is exporting form configurations, which include integration keys (like HubSpot or Google Sheets settings if stored in the module) and notification logic.

HTTP Request:

  • URL: http://[target]/wp-admin/admin.php?page=forminator-cform
  • Method: POST (or GET, but POST is used by the UI)
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    forminator_action=export&id=[TARGET_FORM_ID]&_wpnonce=[EXTRACTED_NONCE]
    

Expected Response: A JSON file containing the full configuration of the targeted form.

Scenario: Denial of Service (Module Deletion)

HTTP Request:

  • URL: http://[target]/wp-admin/admin.php?page=forminator-cform
  • Method: POST
  • Body:
    forminator_action=delete&id=[TARGET_FORM_ID]&_wpnonce=[EXTRACTED_NONCE]
    

6. Test Data Setup

  1. Install Forminator 1.51.1.
  2. Create Admin Form: Use the admin account to create a Contact Form (ID 1).
  3. Create Subscriber: Create a user attacker with the subscriber role.
  4. Grant Limited Access:
    • Go to Forminator > Settings > Permissions.
    • Enable "Custom Permissions".
    • Grant the subscriber role access to "Reports" and "Templates", but uncheck "Forms", "Polls", and "Quizzes".
  5. Verify Restriction: Ensure the attacker user cannot normally visit admin.php?page=forminator-cform (they should see "You do not have sufficient permissions").

7. Expected Results

  • Export Action: The request returns a 200 OK with a Content-Disposition: attachment header and a JSON payload representing the form configuration.
  • Delete Action: The targeted form is moved to the trash or deleted from the wp_posts table (Forminator stores forms as forminator_forms post type).

8. Verification Steps

  1. Verify Export via CLI:
    • No specific CLI command for form content, but check if the HTTP response starts with {"type":"form".
  2. Verify Deletion via CLI:
    wp post list --post_type=forminator_forms --post_status=any
    
    Confirm that the form with the targeted ID is either missing or has its post_status changed.

9. Alternative Approaches

If forminator-cform page strictly blocks the request before admin_menu finishes, try targeting the forminator-poll or forminator-quiz pages, as they use the same abstract base class:

  • admin.php?page=forminator-poll&forminator_action=export&id=[ID]&_wpnonce=[NONCE]
  • admin.php?page=forminator-quiz&forminator_action=export&id=[ID]&_wpnonce=[NONCE]

Additionally, check for bulk_action variants if single ID actions are blocked:

  • Body: forminator_action=bulk_delete&ids[]=[ID1]&ids[]=[ID2]&_wpnonce=[NONCE]
Research Findings
Static analysis — not yet PoC-verified

Summary

Forminator Forms is vulnerable to an authorization bypass where authenticated users (e.g., Subscribers) granted access to limited Forminator sections (like Reports or Templates) can execute administrative actions on any form, poll, or quiz. This occurs because the `processRequest` method dispatches sensitive actions such as exporting, deleting, or cloning modules after only a nonce check, without verifying if the user has the required `manage_forminator_modules` capability.

Vulnerable Code

/* admin/abstracts/class-admin-module-edit-page.php:91 */
public function init() {
	$pagenum           = absint( Forminator_Core::sanitize_text_field( 'paged' ) );
	self::$page_number = max( 1, $pagenum );
	$this->processRequest();
}

---

/* admin/abstracts/class-admin-module-edit-page.php:984 */
public function processRequest() {
	$action = Forminator_Core::sanitize_text_field( 'forminator_action' );
	if ( ! $action ) {
		return;
	}

	$id               = Forminator_Core::sanitize_text_field( 'id' );
	$plural_slug      = static::$module_slug . 's';
	$nonce            = Forminator_Core::sanitize_text_field( '_wpnonce' );
	$success          = false;
	$text_message     = '';

	if ( ! wp_verify_nonce( $nonce, 'forminator_form_request' ) ) {
		return;
	}

	switch ( $action ) {
		case 'delete':
			// Action execution logic without capability checks

Security Fix

--- admin/abstracts/class-admin-module-edit-page.php
+++ admin/abstracts/class-admin-module-edit-page.php
@@ -94,6 +94,10 @@
 	public function init() {
 		$pagenum           = absint( Forminator_Core::sanitize_text_field( 'paged' ) );
 		self::$page_number = max( 1, $pagenum );
+
+		if ( ! current_user_can( 'manage_forminator_modules' ) ) {
+			return;
+		}
 		$this->processRequest();
 	}

Exploit Outline

To exploit this vulnerability, an attacker requires an authenticated account that has been granted permission to access at least one Forminator admin page (such as 'Reports' or 'Templates'). The attacker first visits an accessible Forminator page and extracts the 'forminator_form_request' nonce from the global 'forminatorData' JavaScript object. They then identify the ID of a target module (form, poll, or quiz) and craft a POST request to an administrative endpoint (e.g., admin.php?page=forminator-cform) containing the 'forminator_action' parameter set to 'export', 'delete', or 'clone', the target 'id', and the extracted nonce. Despite the attacker lacking module-management permissions, the plugin's 'processRequest' method will execute the action, potentially disclosing sensitive configuration data like integration credentials or deleting forms.

Check if your site is affected.

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