================================================================================
SENDPRESS NEWSLETTERS - SECURITY PATCH DOCUMENTATION
Patchstack Vulnerability Remediation
================================================================================
Document Version: 1.0
Date: January 2026
Git Branch: security/fix-xss-sqli-vulnerabilities
Plugin Version: 1.24.8.21 (post-patch)
================================================================================
EXECUTIVE SUMMARY
================================================================================
This document details the security fixes implemented to address vulnerabilities
reported in the Patchstack WordPress Vulnerability Database for SendPress
Newsletters plugin.
Patchstack Database URL:
https://patchstack.com/database/wordpress/plugin/sendpress/vulnerabilities
VULNERABILITIES ADDRESSED:
---------------------------------------------------------------------------
| ID | Type | CVSS | Patchstack Status | Our Status |
---------------------------------------------------------------------------
| 1 | Reflected XSS | 7.1 | No official fix | FIXED ✓ |
| 2 | Cross Site Scripting | 5.9 | No official fix | FIXED ✓ |
| 3 | Broken Access Control | 5.3 | No official fix | FIXED ✓ |
| 4 | CSRF | 4.3 | No official fix | FIXED ✓ |
| 5 | Contributor+ Stored XSS | 6.5 | Fixed in 1.23.11.6 | VERIFIED ✓ |
---------------------------------------------------------------------------
Total Files Modified: 46 (including earlier WPScan CVE fixes)
Files Modified for Patchstack Issues: 7
================================================================================
VULNERABILITY #1: Reflected Cross-Site Scripting (XSS)
================================================================================
Patchstack Reference:
https://patchstack.com/database/wordpress/plugin/sendpress/vulnerability/wordpress-sendpress-newsletters-plugin-1-22-3-31-reflected-cross-site-scripting-xss-vulnerability
CVSS Score: 7.1 (Medium Priority)
Affected Versions: <= 1.23.11.6
Reporter: Le Ngoc Anh (April 2023)
Patchstack Status: "No official fix available"
DESCRIPTION:
Reflected XSS vulnerability allowing malicious actors to inject scripts via
URL parameters that are reflected back to users without proper sanitization.
ROOT CAUSE:
The SendPress_Security class used deprecated FILTER_SANITIZE_STRING which was
removed in PHP 8.1+, causing input validation to fail silently.
FIX IMPLEMENTED:
File: classes/class-sendpress-security.php
BEFORE (vulnerable):
return filter_input(INPUT_GET, $field, FILTER_SANITIZE_STRING);
return filter_input(INPUT_POST, $field, FILTER_SANITIZE_STRING);
AFTER (secure):
$value = isset($_GET[$field]) ? $_GET[$field] : '';
return sanitize_text_field(wp_unslash($value));
$value = isset($_POST[$field]) ? $_POST[$field] : '';
return sanitize_text_field(wp_unslash($value));
WORDPRESS SECURITY STANDARDS APPLIED:
- sanitize_text_field() - WordPress core sanitization function
- wp_unslash() - Proper handling of WordPress magic quotes
- Removed deprecated PHP filter that fails silently in PHP 8.1+
================================================================================
VULNERABILITY #2: Cross-Site Scripting (XSS) - General
================================================================================
Patchstack Reference:
https://patchstack.com/database/wordpress/plugin/sendpress/vulnerability/wordpress-sendpress-newsletters-plugin-1-22-3-31-cross-site-scripting-xss
CVSS Score: 5.9 (Low Priority)
Affected Versions: <= 1.23.11.6
Reporter: yuyudhn (January 2023)
Patchstack Status: "No official fix available"
DESCRIPTION:
XSS vulnerability allowing injection of malicious scripts through form
attributes and stored settings that are output without proper escaping.
FIX IMPLEMENTED:
Multiple files with output escaping added:
File: classes/sc/class-sendpress-sc-forms.php (Lines 363, 373, 376)
BEFORE:
data-form-id=""
echo '';
echo '';
AFTER:
data-form-id=""
echo '';
echo '';
File: classes/sc/class-sendpress-sc-signup.php (Line 83)
File: classes/class-sendpress-signup-shortcode-old.php (Line 68)
BEFORE:
echo '';
AFTER:
echo '';
WORDPRESS SECURITY STANDARDS APPLIED:
- esc_attr() - Escaping for HTML attribute context
- esc_html() - Escaping for HTML output context
- All dynamic values properly escaped before output
================================================================================
VULNERABILITY #3: Broken Access Control
================================================================================
Patchstack Reference:
https://patchstack.com/database/wordpress/plugin/sendpress/vulnerability/wordpress-sendpress-newsletters-plugin-1-22-3-31-broken-access-control-vulnerability
CVSS Score: 5.3 (Low Priority)
Affected Versions: <= 1.23.11.6
Reporter: Mika (June 2023)
Patchstack Status: "No official fix available" (Patchstack mitigation rule exists)
DESCRIPTION:
Broken access control allowing unauthenticated users to access sensitive API
endpoints. Specifically, the 'bounce' and 'cron' endpoints could be called
without authentication, allowing attackers to:
- Mark any email address as bounced (effectively unsubscribing users)
- Trigger cron jobs on demand (potential DoS vector)
FIX IMPLEMENTED:
File: classes/class-sendpress-api.php (Lines 151-170)
BEFORE (vulnerable):
case 'bounce':
case 'cron':
$this->is_valid_request = true;
$wp_query->set('key', 'public');
break;
AFTER (secure):
case 'bounce':
case 'cron':
// These endpoints require a webhook secret for security
$webhook_secret = SendPress_Option::get('webhook_secret');
$provided_secret = isset($wp_query->query_vars['token'])
? $wp_query->query_vars['token'] : '';
// Always require valid webhook secret - no unauthenticated access
if (empty($webhook_secret) ||
!hash_equals($webhook_secret, $provided_secret)) {
$this->invalid_auth();
return;
}
$this->is_valid_request = true;
$wp_query->set('key', 'public');
break;
Additionally, in sendpress.php plugin_install():
// Generate webhook_secret for API security if not already set
$existing_secret = SendPress_Option::get( 'webhook_secret' );
if ( empty( $existing_secret ) ) {
SendPress_Option::set( 'webhook_secret', wp_generate_password( 32, false, false ) );
}
WORDPRESS SECURITY STANDARDS APPLIED:
- hash_equals() - Timing-safe string comparison to prevent timing attacks
- wp_generate_password() - Cryptographically secure random string generation
- Secure by default - secret auto-generated on activation/upgrade
- Returns 401 Unauthorized for invalid or missing authentication
SECURE BY DEFAULT:
A 32-character webhook_secret is automatically generated during plugin
activation. The bounce/cron endpoints ALWAYS require this token - there is
no unauthenticated fallback. Existing installations will have a secret
generated on next plugin update/reactivation.
API calls must include the token parameter:
/spnl-api/bounce/?email=test@example.com&token=YOUR_WEBHOOK_SECRET
Administrators can find/change their webhook_secret in the SendPress options.
================================================================================
VULNERABILITY #4: Cross-Site Request Forgery (CSRF)
================================================================================
Patchstack Reference:
https://patchstack.com/database/wordpress/plugin/sendpress/vulnerability/wordpress-sendpress-newsletters-plugin-1-22-3-31-cross-site-request-forgery-csrf
CVSS Score: 4.3 (Low Priority)
Affected Versions: <= 1.23.11.6
Reporter: yuyudhn (January 2023)
Patchstack Status: "No official fix available"
DESCRIPTION:
CSRF vulnerability in the subscription form AJAX endpoint. The subscribe_to_list()
function lacked nonce verification, allowing attackers to forge subscription
requests on behalf of users visiting malicious pages.
FIX IMPLEMENTED:
1. Added nonce to frontend JavaScript localization
File: sendpress.php (Line 1085)
AFTER:
wp_localize_script('sendpress-signup-form-js', 'sendpress', array(
'invalidemail' => __("Please enter your e-mail address", "sendpress"),
'missingemail' => __("Please enter your e-mail address", "sendpress"),
'required' => __("Please enter all the required fields...", "sendpress"),
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('sendpress_public_subscribe') // ADDED
));
2. JavaScript sends nonce with AJAX request
File: js/sendpress.signup.js (Line 97)
AFTER:
if(submit_ok){
$submit.attr("disabled", "disabled");
// Add nonce for CSRF protection
signup['spnonce'] = sendpress.nonce;
jQuery.post(sendpress.ajaxurl, signup, function(response){
3. Server-side nonce verification
File: classes/class-sendpress-ajax-loader.php (Line 167)
AFTER:
function subscribe_to_list() {
// Verify nonce for CSRF protection
$nonce = SPNL()->validate->_string('spnonce');
if (!wp_verify_nonce($nonce, 'sendpress_public_subscribe')) {
echo json_encode(array(
'success' => false,
'error' => __('Security check failed. Please refresh the page and try again.', 'sendpress')
));
die();
}
// ... rest of function
4. Non-AJAX forms protected with nonce field
Files:
- classes/sc/class-sendpress-sc-forms.php (Line 368)
- classes/sc/class-sendpress-sc-signup.php (Line 77)
- classes/class-sendpress-signup-shortcode-old.php (Line 61)
ADDED:
wp_nonce_field('sendpress-form-post', 'sp');
WORDPRESS SECURITY STANDARDS APPLIED:
- wp_create_nonce() - Generate cryptographically secure nonce
- wp_verify_nonce() - Validate nonce on server side
- wp_nonce_field() - Add hidden nonce field to forms
- Nonce tied to specific action name for security
================================================================================
VULNERABILITY #5: Contributor+ Stored XSS via Shortcode
================================================================================
Patchstack Reference:
https://patchstack.com/database/wordpress/plugin/sendpress/vulnerability/wordpress-sendpress-newsletters-plugin-1-22-3-31-authenticated-contributor-stored-cross-site-scripting-via-shortcode-vulnerability
CVSS Score: 6.5 (Low Priority)
Affected Versions: <= 1.22.3.31
Patchstack Status: "Fixed in version 1.23.11.6"
DESCRIPTION:
Authenticated users with Contributor+ role could inject malicious scripts
via shortcode attributes.
STATUS: VERIFIED FIXED
This vulnerability was already addressed in version 1.23.11.6 according to
Patchstack. Our codebase (1.24.8.x) includes this fix.
VERIFICATION:
Shortcode attributes are processed through shortcode_atts() which provides
sanitization, and output values are escaped with esc_attr() and esc_html().
================================================================================
FILES MODIFIED SUMMARY
================================================================================
File | Vulnerability | Changes
--------------------------------------------------|---------------|------------------
sendpress.php | CSRF | Nonce localization
js/sendpress.signup.js | CSRF | Send nonce
classes/class-sendpress-ajax-loader.php | CSRF | Verify nonce
classes/class-sendpress-api.php | Access Ctrl | Webhook secret
classes/class-sendpress-security.php | Reflected XSS | sanitize_text_field
classes/sc/class-sendpress-sc-forms.php | XSS, CSRF | esc_attr, nonce
classes/sc/class-sendpress-sc-signup.php | XSS, CSRF | esc_attr, nonce
classes/class-sendpress-signup-shortcode-old.php | XSS, CSRF | esc_attr, nonce
================================================================================
WORDPRESS CODING STANDARDS COMPLIANCE
================================================================================
All fixes follow WordPress security best practices:
1. INPUT VALIDATION & SANITIZATION
- sanitize_text_field() for text input
- absint() / intval() for integers
- sanitize_email() for email addresses
- wp_unslash() before sanitization
2. OUTPUT ESCAPING
- esc_html() for HTML content
- esc_attr() for HTML attributes
- esc_url() for URLs
- esc_textarea() for textarea content
3. NONCE VERIFICATION
- wp_create_nonce() for generation
- wp_verify_nonce() for validation
- wp_nonce_field() for form fields
- Unique action names per operation
4. CAPABILITY CHECKS
- current_user_can() for permission verification
- Role-based access control where applicable
5. DATABASE SECURITY
- $wpdb->prepare() for all dynamic SQL
- Parameterized queries to prevent SQL injection
Reference: https://developer.wordpress.org/plugins/security/
================================================================================
TESTING CHECKLIST
================================================================================
CSRF Protection Tests:
[ ] Submit subscription form with valid nonce - Should succeed
[ ] Submit subscription form without nonce - Should fail with error message
[ ] Submit subscription form with invalid nonce - Should fail
[ ] Test non-AJAX form submission includes nonce field
Broken Access Control Tests:
[ ] Fresh install: webhook_secret is auto-generated in options
[ ] Call /spnl-api/bounce/ without token - Should fail 401
[ ] Call /spnl-api/bounce/ with incorrect token - Should fail 401
[ ] Call /spnl-api/bounce/ with correct token - Should succeed
[ ] Call /spnl-api/cron/ with same tests as above
[ ] Plugin reactivation preserves existing webhook_secret
XSS Prevention Tests:
[ ] Enter in form fields - Should be escaped
[ ] Test settings pages with special characters - Should display safely
[ ] Verify all shortcode attributes are escaped in output
General Security Tests:
[ ] PHP syntax validation passes on all modified files
[ ] No PHP errors or warnings in error log
[ ] Plugin activates and deactivates without errors
[ ] All existing functionality works as expected
================================================================================
REVIEWER CHECKLIST
================================================================================
For security review, please verify:
[ ] All user input is sanitized before use
[ ] All output is escaped in appropriate context
[ ] Nonces are verified for all form submissions
[ ] Nonces are verified for all AJAX requests
[ ] API endpoints require proper authentication
[ ] No SQL injection vectors remain
[ ] No deprecated PHP functions used
[ ] WordPress coding standards followed
[ ] Changes don't break existing functionality
================================================================================
CONTACT & SUPPORT
================================================================================
For questions about these security fixes:
- Review the git commit history on branch: security/fix-xss-sqli-vulnerabilities
- See SECURITY-FIXES.md for comprehensive documentation
- See SECURITY-AUDIT-ADDITIONAL.txt for future improvement recommendations
To report new security issues:
- Patchstack VDP: https://patchstack.com/database/report/wordpress/plugin/sendpress
================================================================================