JetFormBuilder <= 3.5.3 - Missing Authorization to Unauthenticated Form Generation
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:NTechnical Details
<=3.5.3Source Code
WordPress.org SVNThis 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 therun_callbackfunction 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
- The plugin registers an AJAX handler for the AI generation feature.
- 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 - The
run_callbackfunction receives the request parameters. - The function proceeds to contact the AI API and return a generated form structure.
- 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).
- Identify Shortcode/Block: JetFormBuilder uses blocks. To ensure the scripts load, create a page with a JetFormBuilder block.
- 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 - Extract Nonce via Browser:
Navigate to the newly created page or the WordPress dashboard. Usebrowser_evalto search for localized data.- JS Variable: Likely
window.JetFormBuilderAiConfigorwindow.jetFormBuilderData. - Command:
browser_eval("window.JetFormBuilderAiConfig?.nonce")orbrowser_eval("window.jetFormBuilderData?.ai_nonce").
- JS Variable: Likely
- Verification: Compare the action string in
wp_create_noncewith the one used incheck_ajax_refererwithin 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
- Install Plugin: Ensure JetFormBuilder v3.5.3 is installed.
- 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).
- 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 OKresponse 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 Forbiddenor 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:
- Check Logs: If a dummy key was used, check the WordPress debug log (
wp-content/debug.log) for errors originating fromJetFormBuilder\Modules\Ai\Action_Ai_Callback::run_callback. - Monitor Usage: If using a real API key, verify if a request was logged in the AI provider's dashboard.
- Code Inspection: Use
grepto confirm the absence of authorization checks in the vulnerable version:grep -r "function run_callback" wp-content/plugins/jetformbuilder/includes/
Verify ifcurrent_user_canorcheck_admin_refereris 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_refereris completely missing fromrun_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 thedieparameter as false) and the return value is not checked, the exploit will succeed even with an invalid nonce.
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
@@ -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.