CVE-2025-15380

NotificationX <= 3.2.0 - Unauthenticated DOM-Based Cross-Site Scripting via 'nx-preview'

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
3.2.1
Patched in
1d
Time to patch

Description

The NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar plugin for WordPress is vulnerable to DOM-Based Cross-Site Scripting via the 'nx-preview' POST parameter in all versions up to, and including, 3.2.0. This is due to insufficient input sanitization and output escaping when processing preview data. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute when a user visits a malicious page that auto-submits a form to the vulnerable site.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.2.0
PublishedJanuary 20, 2026
Last updatedJanuary 20, 2026
Affected pluginnotificationx

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan targets **CVE-2025-15380**, a DOM-based Cross-Site Scripting (XSS) vulnerability in the **NotificationX** plugin. The vulnerability exists because the plugin processes a `POST` parameter named `nx-preview` and reflects it into the page context without adequate sanitiz…

Show full research plan

This exploitation research plan targets CVE-2025-15380, a DOM-based Cross-Site Scripting (XSS) vulnerability in the NotificationX plugin. The vulnerability exists because the plugin processes a POST parameter named nx-preview and reflects it into the page context without adequate sanitization, which is subsequently executed by the plugin's frontend JavaScript.


1. Vulnerability Summary

  • Vulnerability: Unauthenticated DOM-Based XSS.
  • Vulnerable Parameter: nx-preview (POST).
  • Component: Notification Preview Engine.
  • Reason: The plugin allows users to "preview" notifications by sending their configuration via a POST request. The plugin reflects this configuration into a global JavaScript variable or a data attribute on the frontend. The plugin's client-side scripts then use this data to render a notification using dangerous DOM sinks (like .innerHTML or jQuery's .html()) without escaping the content.

2. Attack Vector Analysis

  • Endpoint: Any frontend page (e.g., the homepage /) or pages where NotificationX scripts are loaded.
  • HTTP Method: POST.
  • Authentication: None required (Unauthenticated).
  • Preconditions:
    1. The plugin must be active.
    2. An attacker must obtain a valid nonce (accessible to unauthenticated users) to pass the check_ajax_referer or wp_verify_nonce check usually associated with preview functionality.
  • Payload Delivery: Since it requires a POST request, the typical delivery is via a malicious site that auto-submits an external form to the target WordPress site (Cross-Site Request Forgery as a delivery mechanism for XSS).

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers a handler on the init or wp_loaded hook that checks for the existence of $_POST['nx-preview'].
  2. Processing:
    • The handler verifies a nonce (e.g., nx-preview).
    • The content of $_POST['nx-preview'] (expected to be a JSON string) is captured.
  3. Reflected Sink (PHP): The handler echoes the raw or partially sanitized JSON into the HTML response, likely inside a <script> tag:
    var notificationx_preview_data = {"title": "...[PAYLOAD]..." };
  4. Execution Sink (JS): The plugin's frontend script (e.g., notificationx-public.js) reads notificationx_preview_data. It iterates through the object and renders the notification. It likely uses a sink such as:
    jQuery('.nx-title').html(previewData.title);

4. Nonce Acquisition Strategy

NotificationX exposes nonces for its frontend functionality through wp_localize_script.

  1. Identify Shortcode: The plugin's scripts are typically enqueued when a notification is active or when the [notificationx] shortcode is present.
  2. Create Test Page:
    wp post create --post_type=page --post_title="XSS Test" --post_status=publish --post_content='[notificationx]'
    
  3. Extract Nonce:
    Navigate to the newly created page and use browser_eval to find the nonce in the localized object.
    • Variable Name: window.notificationx_ajax (inferred from common NotificationX patterns).
    • Nonce Key: nx_preview_nonce or nonce.
    • Extraction Command: browser_eval("window.notificationx_ajax?.nx_preview_nonce")

5. Exploitation Strategy

Step 1: Discover the Nonce

Navigate to the homepage or the test page and extract the required nonce.

Step 2: Construct the Payload

The nx-preview parameter expects a JSON object representing a notification.
Payload:

{
  "type": "sales",
  "content": "<img src=x onerror=alert(document.domain)>",
  "template_id": 1
}

Step 3: Execute the POST Request

Use the http_request tool to simulate the auto-submitting form.

  • URL: https://<target-site>/
  • Method: POST
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
  • Body:
    action=nx_preview_action&nx_preview_nonce=[NONCE]&nx-preview={"type":"sales","content":"<img src=x onerror=alert(1)>"}
    (Note: The exact 'action' parameter may vary; it is often required for the init hook to route the request properly if it uses admin-ajax logic.)

6. Test Data Setup

  1. Plugin Installation: Ensure notificationx version 3.2.0 or lower is installed.
  2. Active Notification: Create at least one "Sales" notification via the WordPress admin to ensure frontend scripts are initialized correctly.
    # (Assuming WP-CLI support for the plugin)
    wp notificationx create --type=sales --title="Test"
    
  3. Public Page: Ensure a page exists with the [notificationx] shortcode to leak the nonce.

7. Expected Results

  • The HTTP response should contain the JSON payload reflected within a <script> block or a hidden input.
  • Upon rendering the page, the browser's JavaScript will process the nx-preview JSON.
  • The malicious <img> tag in the content field will be injected into the DOM via a method like .html().
  • The onerror event will trigger, executing alert(1).

8. Verification Steps

  1. Manual Inspection: Use http_request to verify the payload is present in the response body.
    # Search for the reflected payload in the HTML response
    grep "onerror=alert" response.html
    
  2. Automated Execution: Use browser_navigate to the URL with the POST parameters (or use a local HTML file that auto-submits to the target) and check for a JavaScript dialog or a specific console log.

9. Alternative Approaches

  • Base64 Encoding: Some versions of NotificationX expect the nx-preview parameter to be Base64 encoded. If raw JSON fails, try:
    nx-preview=eyJ0eXBlIjoic2FsZXMiLCJjb250ZW50IjoiPGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPiJ9
  • Direct Parameter Injection: Check if the plugin accepts the data via $_GET['nx-preview'] as well, though the description specifically highlights POST.
  • Different Templates: NotificationX has various notification types (Sales, Review, Announcement). If "Sales" is sanitized, "Announcement" or "Custom" might not be. Test the nx-preview JSON with different type keys.
Research Findings
Static analysis — not yet PoC-verified

Summary

The NotificationX plugin for WordPress is vulnerable to unauthenticated DOM-based Cross-Site Scripting (XSS) via the 'nx-preview' POST parameter in versions up to 3.2.0. The vulnerability is caused by insufficient input sanitization when processing notification preview data, which is then reflected into the page and rendered using unsafe JavaScript sinks. An attacker can exploit this by tricking a victim into visiting a page that auto-submits a malicious POST request, executing arbitrary scripts in their browser context.

Vulnerable Code

/* Inferred from client-side sink logic in scripts like notificationx-public.js */
jQuery('.nx-title').html(previewData.title);

---

/* Inferred from server-side reflection of the nx-preview POST parameter */
var notificationx_preview_data = {"title": "...[PAYLOAD]..." };

Exploit Outline

1. Access the target WordPress site's frontend and extract a valid 'nx_preview_nonce' from the 'window.notificationx_ajax' localized script object. 2. Construct a malicious JSON payload representing a notification configuration (e.g., {"type":"sales","content":"<img src=x onerror=alert(1)>"}). 3. Craft a POST request to any page on the site where NotificationX scripts are loaded, including the parameters 'action=nx_preview_action', 'nx_preview_nonce', and the malicious 'nx-preview' JSON (which may need to be Base64 encoded depending on the specific version). 4. Use a CSRF-style auto-submitting form on an attacker-controlled page to force a victim's browser to send the POST request. 5. When the page renders, the plugin's JavaScript will read the reflected payload and inject it into the DOM using an unsafe sink like jQuery's .html(), triggering the execution of the arbitrary script.

Check if your site is affected.

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