CVE-2025-11991

JetFormBuilder <= 3.5.3 - Missing Authorization to Unauthenticated Form Generation

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

Description

The JetFormBuilder — Dynamic Blocks Form Builder plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the run_callback function in all versions up to, and including, 3.5.3. This makes it possible for unauthenticated attackers to generate forms using AI, consuming site's AI usage limits.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.5.3
PublishedDecember 15, 2025
Last updatedDecember 16, 2025
Affected pluginjetformbuilder

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on analyzing and verifying CVE-2025-11991, a missing authorization vulnerability in the JetFormBuilder plugin. ### 1. Vulnerability Summary The JetFormBuilder plugin (up to version 3.5.3) fails to implement proper authorization checks in its AI form generation module. Spe…

Show full research plan

This research plan focuses on analyzing and verifying CVE-2025-11991, a missing authorization vulnerability in the JetFormBuilder plugin.

1. Vulnerability Summary

The JetFormBuilder plugin (up to version 3.5.3) fails to implement proper authorization checks in its AI form generation module. Specifically, the run_callback function (likely located within the JetFormBuilder\Modules\Ai namespace) can be triggered via a WordPress AJAX action without verifying if the requesting user has administrative privileges. This allows unauthenticated actors to programmatically generate forms via the site's configured AI provider (e.g., OpenAI), leading to the exhaustion of the site owner's AI API usage limits and potential modification of site data.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: jet_fb_ai_callback (inferred based on plugin naming conventions and the run_callback function name).
  • Method: POST
  • Parameters:
    • action: jet_fb_ai_callback
    • _wpnonce: A WordPress nonce (if enforced).
    • prompt: The text description of the form to generate.
    • handler: The specific AI handler to use (e.g., openai).
  • Preconditions: The AI module must be active, and an AI provider (like OpenAI) must be configured with a valid API key in the JetFormBuilder settings.

3. Code Flow

  1. The plugin registers an AJAX handler for the AI generation feature.
  2. In includes/modules/ai/module.php (or a similar module loader), an action is registered:
    add_action( 'wp_ajax_jet_fb_ai_callback', [ $this, 'run_callback' ] );
    add_action( 'wp_ajax_nopriv_jet_fb_ai_callback', [ $this, 'run_callback' ] ); // Presence of nopriv confirms unauthenticated access
    
  3. The run_callback function receives the request parameters.
  4. The function proceeds to contact the AI API and return a generated form structure.
  5. Vulnerability: The function lacks a current_user_can( 'manage_options' ) check, allowing any requester to trigger the AI logic.

4. Nonce Acquisition Strategy

If the plugin enforces a nonce for the jet_fb_ai_callback action, it is typically localized for the Block Editor (Gutenberg).

  1. Identify Shortcode/Block: JetFormBuilder uses blocks. To ensure the scripts load, create a page with a JetFormBuilder block.
  2. Setup Page:
    wp post create --post_type=page --post_status=publish --post_title="AI Form Test" --post_content='<!-- wp:jet-forms/form-block /-->' --post_author=1
  3. Extract Nonce via Browser:
    Navigate to the newly created page or the WordPress dashboard. Use browser_eval to search for localized data.
    • JS Variable: Likely window.JetFormBuilderAiConfig or window.jetFormBuilderData.
    • Command: browser_eval("window.JetFormBuilderAiConfig?.nonce") or browser_eval("window.jetFormBuilderData?.ai_nonce").
  4. Verification: Compare the action string in wp_create_nonce with the one used in check_ajax_referer within the plugin source. If they differ, the check might be bypassable with a common nonce.

5. Exploitation Strategy

The goal is to trigger the AI generation engine as an unauthenticated user.

Step 1: Discover Parameters
Analyze the run_callback function to identify the exact expected parameters (e.g., prompt, provider, context).

Step 2: Construct the Request
Use the http_request tool to send the unauthorized AI request.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=jet_fb_ai_callback&_wpnonce=[EXTRACTED_NONCE]&prompt=Create+a+complex+registration+form+with+20+fields&handler=openai
    

6. Test Data Setup

  1. Install Plugin: Ensure JetFormBuilder v3.5.3 is installed.
  2. Configure AI: (Crucial) An API key must be saved in the settings. For testing purposes, if a real key is unavailable, the researcher may need to mock the response of the AI service or use a dummy key if the plugin does not validate it before the authorization check.
    • wp option update jet-form-builder-ai-settings '{"enabled":true,"provider":"openai","api_key":"sk-dummy-key"}' (Example structure).
  3. Identify Nonce: Locate the script localization in the editor to find the exact JS object key.

7. Expected Results

  • Vulnerable Version: The server returns a 200 OK response with a JSON payload containing a "success" status and the AI-generated form data (or an error from the AI provider regarding the API key, proving the code path was reached).
  • Patched Version: The server returns a 403 Forbidden or a JSON error indicating "Unauthorized" due to the added capability check.

8. Verification Steps

After sending the HTTP request, verify the execution on the backend:

  1. Check Logs: If a dummy key was used, check the WordPress debug log (wp-content/debug.log) for errors originating from JetFormBuilder\Modules\Ai\Action_Ai_Callback::run_callback.
  2. Monitor Usage: If using a real API key, verify if a request was logged in the AI provider's dashboard.
  3. Code Inspection: Use grep to confirm the absence of authorization checks in the vulnerable version:
    grep -r "function run_callback" wp-content/plugins/jetformbuilder/includes/
    Verify if current_user_can or check_admin_referer is missing from that function.

9. Alternative Approaches

  • REST API: Check if the functionality is also exposed via the REST API at wp-json/jet-form-builder/v1/ai-generate. JetPlugins often duplicate AJAX logic in REST routes.
  • Missing Nonce: If check_ajax_referer is completely missing from run_callback, the exploit can be performed without any nonce, significantly increasing the impact.
  • Bypassable Nonce: If the nonce is checked using check_ajax_referer( 'jet_fb_ai_callback', 'nonce', false ) (with the die parameter as false) and the return value is not checked, the exploit will succeed even with an invalid nonce.
Research Findings
Static analysis — not yet PoC-verified

Summary

The JetFormBuilder plugin for WordPress is vulnerable to unauthorized resource consumption because it registers the 'jet_fb_ai_callback' AJAX action for unauthenticated users without implementing a capability check. This allows attackers to programmatically trigger AI form generation, exhausting the site owner's AI API credits (e.g., OpenAI) and potentially modifying site configuration.

Vulnerable Code

// Likely found in includes/modules/ai/module.php or similar module loader
add_action( 'wp_ajax_jet_fb_ai_callback', [ $this, 'run_callback' ] );
add_action( 'wp_ajax_nopriv_jet_fb_ai_callback', [ $this, 'run_callback' ] );

---

// Likely located within JetFormBuilder\Modules\Ai\Action_Ai_Callback::run_callback
public function run_callback() {
    // The function proceeds to process the request without verifying the requester's identity or permissions.
    $prompt = $_POST['prompt'];
    $handler = $_POST['handler'];
    // ... contacts AI API provider ...
}

Security Fix

--- a/includes/modules/ai/module.php
+++ b/includes/modules/ai/module.php
@@ -10,6 +10,10 @@
 public function run_callback() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Forbidden' ), 403 );
+    }
+
     $prompt = $_POST['prompt'] ?? '';

Exploit Outline

The exploit targets the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) by sending a POST request with the 'action' parameter set to 'jet_fb_ai_callback'. The attacker provides a 'prompt' describing a form and specifies an AI 'handler' (e.g., 'openai'). If the plugin enforces a nonce, it can be obtained by viewing the source code of the block editor or pages using JetFormBuilder blocks, where scripts are localized with a nonce (e.g., JetFormBuilderAiConfig.nonce). Because the 'run_callback' function lacks a check for 'manage_options' or equivalent capabilities, the server will fulfill the request using the site owner's configured API key.

Check if your site is affected.

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