CVE-2026-3090

Post SMTP <= 3.8.0 - Unauthenticated Stored Cross-Site Scripting via 'event_type'

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

Description

The Post SMTP – Complete Email Deliverability and SMTP Solution with Email Logs, Alerts, Backup SMTP & Mobile App plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the ‘event_type’ parameter in all versions up to, and including, 3.8.0 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. The vulnerability is only exploitable when the Post SMTP Pro plugin is also installed and its Reporting and Tracking extension is enabled.

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.8.0
PublishedMarch 17, 2026
Last updatedMarch 18, 2026
Affected pluginpost-smtp

What Changed in the Fix

Changes introduced in v3.9.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-3090 (Post SMTP Stored XSS) ## 1. Vulnerability Summary The **Post SMTP** plugin (specifically when the **Post SMTP Pro** and **Reporting and Tracking** extension are active) is vulnerable to **Unauthenticated Stored Cross-Site Scripting (XSS)**. The vulnerabi…

Show full research plan

Exploitation Research Plan: CVE-2026-3090 (Post SMTP Stored XSS)

1. Vulnerability Summary

The Post SMTP plugin (specifically when the Post SMTP Pro and Reporting and Tracking extension are active) is vulnerable to Unauthenticated Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin accepts the event_type parameter from unauthenticated tracking requests and stores it in the database (post_smtp_tracking table) without sufficient sanitization. This data is later rendered in the Post SMTP Dashboard (wp-admin/admin.php?page=postman) using Vue.js components that fail to escape the stored value, allowing an attacker to execute arbitrary JavaScript in the context of an authenticated administrator.

2. Attack Vector Analysis

  • Endpoint: The public-facing site root with tracking query parameters.
  • Action/Hook: Likely a hook on init or template_redirect registered by the Reporting and Tracking extension to log email opens/clicks.
  • Vulnerable Parameter: event_type.
  • Authentication: None required (Unauthenticated).
  • Preconditions:
    1. Post SMTP (<= 3.8.0) installed and active.
    2. Post SMTP Pro + Reporting and Tracking extension installed and enabled.
    3. Email tracking must be active in the plugin settings.

3. Code Flow

  1. Injection (Public):
    • An unauthenticated request is sent to /?ps-type=track&event_type=<payload> (inferred tracking URL pattern).
    • The Reporting extension processes this request and calls a database insertion method.
    • The event_type value is saved into the $wpdb->prefix . 'post_smtp_tracking' table.
  2. Retrieval (Admin Dashboard):
    • An administrator visits wp-admin/admin.php?page=postman.
    • Postman/Dashboard/NewDashboard.php enqueues Postman/Dashboard/assets/js/app.js.
    • The Dashboard logic (registered via psd/v1 REST API in NewDashboard.php) fetches logs.
    • The REST API returns the raw event_type from the database.
  3. Execution (Browser):
    • app.js (Vue components) receives the JSON response.
    • The data is rendered in the notification bar or event log (CSS classes like .post-smtp-notification-content in app.css suggest where this might appear).
    • Lack of output escaping in the Vue template results in JavaScript execution.

4. Nonce Acquisition Strategy

The injection phase is unauthenticated and typically does not require a nonce as it is intended for tracking pixels in email clients.

The verification phase (accessing the dashboard) uses a REST API nonce. If the automated agent needs to verify the presence of the payload via the REST API directly:

  1. Variable Name: postSmtpNewDashboard (localized in Postman/Dashboard/NewDashboard.php).
  2. Nonce Key: nonce.
  3. Extraction Method:
    • Navigate to wp-admin/admin.php?page=postman.
    • Use browser_eval("window.postSmtpNewDashboard?.nonce").
  4. REST Endpoint: wp-json/psd/v1/get-failed-logs (as seen in app.js axios calls) or a similar endpoint provided by the Pro version for reporting.

5. Exploitation Strategy

The goal is to inject a payload that will execute when the admin views the Post SMTP Dashboard.

Step 1: Injection Request

Send an HTTP GET request to the site root with the malicious event_type.

  • URL: http://[TARGET_URL]/?ps-type=track&event_type=XSS_INJECTED<img src=x onerror=alert(document.domain)>
  • Method: GET
  • Tool: http_request

Step 2: Triggering the XSS

The agent must simulate an administrator viewing the dashboard.

  • Action: Login as admin and navigate to /wp-admin/admin.php?page=postman.
  • Tool: browser_navigate

Step 3: Capture Execution

Check for the alert or the presence of the injected DOM element.

6. Test Data Setup

  1. Install/Activate Post SMTP 3.8.0.
  2. Activate Pro/Reporting Extension: Since this is a Pro feature, the testing environment must have the report-and-tracking-addon-premium or post-smtp-pro plugin folder present to satisfy the check in Postman/Dashboard/NewDashboard.php:
    is_plugin_active( 'report-and-tracking-addon-premium/post-smtp-report-and-tracking.php' )
    
  3. Enable Tracking: Ensure post_smtp_tracking table is created. This usually happens on activation of the Pro addon.
  4. Create a Dummy Log: (Optional) Send a test email via wp-cli to populate the tracking tables if the endpoint requires a valid email_id.

7. Expected Results

  • The http_request to the tracking endpoint should return a 200 OK or a transparent 1x1 pixel.
  • The browser_navigate to the dashboard should result in a JavaScript execution (e.g., alert(document.domain)).
  • Inspection of the HTML in the dashboard should show the unescaped payload within a notification or log list item.

8. Verification Steps

  1. Check Database: Use wp db query to verify the payload is stored:
    wp db query "SELECT * FROM wp_post_smtp_tracking WHERE event_type LIKE '%XSS_INJECTED%';"
    
  2. Check REST API Response: Use the http_request tool (authenticated) to call the dashboard API and see the unescaped payload in the JSON:
    # Get nonce first via browser_eval
    # Then call API
    GET /wp-json/psd/v1/get-failed-logs
    Header: X-WP-Nonce: [NONCE]
    

9. Alternative Approaches

If /?ps-type=track fails:

  • Try /?ps-event=track&event_type=...
  • Try POST to the same endpoint.
  • Search the plugin source (if available) for $_GET['event_type'] or $_POST['event_type'] to find the exact hook handling the tracking data.
  • Payload Variation: Use a payload that breaks out of common Vue attributes if it's rendered inside a directive: {{8*8}} or "><script>alert(1)</script>.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Post SMTP plugin (when the Pro Reporting and Tracking extension is active) allows unauthenticated attackers to store malicious JavaScript via the 'event_type' parameter in tracking requests. This script executes in the context of an administrator's browser when they access the plugin's dashboard.

Vulnerable Code

// Postman/Dashboard/NewDashboard.php - Line 89
// The code retrieves event_type from the tracking table which is populated by external requests.
public function opened_email_count( $count, $args ) {
    $current_time = $args['current_time'];
    $filter       = $args['filter'];

    global $wpdb;
    $sql = 'SELECT COUNT( * ) FROM %i WHERE event_type = "open-email" AND time <= %d AND time >= %d';
    $sql = $wpdb->prepare( $sql, $wpdb->prefix . 'post_smtp_tracking', $current_time, $filter );

    return $wpdb->get_var( $sql );
}

---

// Postman/Dashboard/assets/js/app.js
// The Vue components render event logs and notifications fetched from the REST API.
// The data (including event_type) is rendered without proper output escaping,
// allowing for script execution when an admin views the dashboard notification bar.
// Relevant CSS selectors: .post-smtp-notification-content, .post-smtp-notification-title

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/post-smtp/3.8.0/Postman/Dashboard/assets/css/app.css /home/deploy/wp-safety.org/data/plugin-versions/post-smtp/3.9.0/Postman/Dashboard/assets/css/app.css
--- /home/deploy/wp-safety.org/data/plugin-versions/post-smtp/3.8.0/Postman/Dashboard/assets/css/app.css	2026-01-20 06:26:16.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/post-smtp/3.9.0/Postman/Dashboard/assets/css/app.css	2026-03-17 07:12:48.000000000 +0000
@@ -1,34 +1,43 @@
+/*!***************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js!./src/app.css ***!
+  \***************************************************************/
 @import url(https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap);
+/*!**************************************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/vue-loader/dist/index.js??ruleSet[1].rules[6].use[0]!./src/components/post-smtp-app-wrapper.vue?vue&type=style&index=0&id=7c6051c6&scoped=true&lang=css ***!
+  \**************************************************************************************************************************************************************************************************************************************************************************/
 
-.post-smtp__wrapper[data-v-3112b8ca] {
+.post-smtp__wrapper[data-v-7c6051c6] {
 	background: #F9FBFF;
 }
-.mr-25[data-v-3112b8ca] {
+.mr-25[data-v-7c6051c6] {
 	margin-right: 25px;
 }
-.container[data-v-3112b8ca] {
+.container[data-v-7c6051c6] {
 	padding: 0 51px;
 }
-.mt-32[data-v-3112b8ca] {
+.mt-32[data-v-7c6051c6] {
 	margin-top: 32px;
 }
-.app-wrapper[data-v-3112b8ca] {
+.app-wrapper[data-v-7c6051c6] {
 	width: calc( 100% - 276px - 25px );
 }
-.app-sidebar[data-v-3112b8ca] {
+.app-sidebar[data-v-7c6051c6] {
 	width: 276px;
 }
-.float-left[data-v-3112b8ca] {
+.float-left[data-v-7c6051c6] {
 	float: left;
 }
-.clearfix[data-v-3112b8ca]::after {
+.clearfix[data-v-7c6051c6]::after {
 	clear: both;
 	content: "";
 	display: table;
 }

Exploit Outline

The exploit target is the unauthenticated tracking endpoint used by the Post SMTP Pro 'Reporting and Tracking' extension. An attacker sends a GET request to the site root with specific tracking parameters: `/?ps-type=track&event_type=<img src=x onerror=alert(1)>`. The plugin's tracking logic (running on `init` or `template_redirect`) saves this malicious `event_type` into the `post_smtp_tracking` database table without sanitization. When an administrator later logs in and visits the Post SMTP Dashboard (`wp-admin/admin.php?page=postman`), the dashboard's Vue.js frontend fetches the tracking logs via a REST API call to `wp-json/psd/v1/get-failed-logs`. The frontend then renders the raw payload in a notification bar or event list, triggering the stored script.

Check if your site is affected.

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