REPORT / 01
Analysis Report · Folder Analysis cache/newsletter_9.1.0 → cache/newsletter_9.1.1 — CVE-2026-1051
Shared security patch analysis results
02 ·
Lifecycle actions
cancel · resume · skip · regenerate
03 ·
Share this analysis
copy link · embed report
03 ·
CVE Security Analysis & Writeups
ai-generated · per cve
Comprehensive security analysis generated by AI for each confirmed CVE match. Click on a CVE to view the detailed writeup including vulnerability background, technical details, patch analysis, and PoC guide.
CVE-2026-1051
NVD
AI-Generated Analysis
05 ·
Findings
filter · search · paginate
Showing 0 to 0 of 0 results
unsubscription/unsubscription.php
AI: Not Sure
4 true positives
CVE-2026-1051
--- cache/newsletter_9.1.0/unsubscription/unsubscription.php 2026-01-20 00:24:22.900048631 +0000+++ cache/newsletter_9.1.1/unsubscription/unsubscription.php 2026-01-20 00:26:01.382141429 +0000@@ -19,7 +19,7 @@ function __construct() { parent::__construct('unsubscription'); - add_filter('newsletter_replace', [$this, 'hook_newsletter_replace'], 10, 4);+ add_filter('newsletter_replace', [$this, 'hook_newsletter_replace'], 10, 5); add_filter('newsletter_page_text', [$this, 'hook_newsletter_page_text'], 10, 3); add_filter('newsletter_message', [$this, 'hook_newsletter_message'], 9, 3); @@ -48,6 +48,7 @@ $label = empty($attrs['label']) ? __('Unsubscribe', 'newsletter') : $attrs['label']; $b = '<form action="' . esc_attr($this->build_action_url('uc')) . '" method="post" class="tnp-button-form tnp-unsubscribe">';+ $b .= wp_nonce_field('newsletter-unsubscribe', '_wpnonce', true, false); $b .= '<input type="hidden" name="nk" value="' . esc_attr($this->get_user_key($user)) . '">'; $b .= '<button class="tnp-submit">' . esc_html($label) . '</button>'; $b .= '</form>';@@ -63,6 +64,7 @@ $label = empty($attrs['label']) ? __('Resubscribe', 'newsletter') : $attrs['label']; $b = '<form action="' . esc_attr($this->build_action_url('reactivate')) . '" method="post" class="tnp-button-form tnp-reactivate">';+ $b .= wp_nonce_field('newsletter-reactivate', '_wpnonce', true, false); $b .= '<input type="hidden" name="nk" value="' . esc_attr($this->get_user_key($user)) . '">'; $b .= '<button class="tnp-submit">' . esc_html($label) . '</button>'; $b .= '</form>';@@ -137,7 +139,10 @@ break; case 'uc':-+ $verified = wp_verify_nonce($_REQUEST['_wpnonce'], 'newsletter-unsubscribe');+ if (!$verified) {+ $this->redirect($this->build_action_url('u', $user, $email));+ } $this->unsubscribe($user, $email); $url = $this->build_message_url(null, 'unsubscribed', $user, $email); setcookie('newsletter', '', 0, '/');@@ -153,6 +158,10 @@ break; case 'reactivate':+ $verified = wp_verify_nonce($_REQUEST['_wpnonce'], 'newsletter-unsubscribe');+ if (!$verified) {+ die('Unverified request');+ } $this->reactivate($user); setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/'); $url = $this->build_message_url(null, 'reactivated', $user);@@ -228,14 +237,28 @@ do_action('newsletter_user_reactivated', $user); } - function hook_newsletter_replace($text, $user, $email, $html = true) {+ function get_unsubscribe_url($user, $email = null) {+ return $this->build_action_url('u', $user, $email);+ }++ function hook_newsletter_replace($text, $user, $email, $html = true, $context = null) { if ($user) {- $text = $this->replace_url($text, 'unsubscription_confirm_url', $this->build_action_url('uc', $user, $email));+ $url = $this->build_action_url('uc', $user, $email);+ if ('page' === $context) {+ $url = wp_nonce_url($url, 'newsletter-unsubscribe');+ }+ $text = $this->replace_url($text, 'unsubscription_confirm_url', $url); $text = $this->replace_url($text, 'unsubscription_url', $this->build_action_url('u', $user, $email)); $text = $this->replace_url($text, 'unsubscribe_url', $this->build_action_url('u', $user, $email));- $text = $this->replace_url($text, 'reactivate_url', $this->build_action_url('reactivate', $user, $email));- $text = $this->replace_url($text, 'reactivation_url', $this->build_action_url('reactivate', $user, $email));++ $url = $this->build_action_url('reactivate', $user, $email);+ if ('page' === $context) {+ $url = wp_nonce_url($url, 'newsletter-reactivate');+ }++ $text = $this->replace_url($text, 'reactivate_url', $url);+ $text = $this->replace_url($text, 'reactivation_url', $url); } else { $text = $this->replace_url($text, 'unsubscription_confirm_url', $this->build_action_url('nul')); $text = $this->replace_url($text, 'unsubscription_url', $this->build_action_url('nul'));
AI Analysis
# Security Analysis - PatchLeaks Code Diff
Based on the provided code diff for `unsubscription/unsubscription.php`, here is my security analysis:
---
## Vulnerability 1
**Vulnerability Existed:** yes
TRUE POSITIVE
**Cross-Site Request Forgery (CSRF) - CWE-352 - unsubscription.php lines 50, 66**
**Old Code:**
```php
$b = '<form action="' . esc_attr($this->build_action_url('uc')) . '" method="post" class="tnp-button-form tnp-unsubscribe">';
$b .= '<input type="hidden" name="nk" value="' . esc_attr($this->get_user_key($user)) . '">';
```
**Fixed Code:**
```php
$b = '<form action="' . esc_attr($this->build_action_url('uc')) . '" method="post" class="tnp-button-form tnp-unsubscribe">';
$b .= wp_nonce_field('newsletter-unsubscribe', '_wpnonce', true, false);
$b .= '<input type="hidden" name="nk" value="' . esc_attr($this->get_user_key($user)) . '">';
```
**Explanation:**
The form was previously missing CSRF protection. The fix adds WordPress nonce field (`wp_nonce_field`) to protect against CSRF attacks. This generates a unique token that is validated server-side before processing the unsubscription request.
---
## Vulnerability 2
**Vulnerability Existed:** yes
TRUE POSITIVE
**Cross-Site Request Forgery (CSRF) - CWE-352 - unsubscription.php lines 66**
**Old Code:**
```php
$b = '<form action="' . esc_attr($this->build_action_url('reactivate')) . '" method="post" class="tnp-button-form tnp-reactivate">';
$b .= '<input type="hidden" name="nk" value="' . esc_attr($this->get_user_key($user)) . '">';
```
**Fixed Code:**
```php
$b = '<form action="' . esc_attr($this->build_action_url('reactivate')) . '" method="post" class="tnp-button-form tnp-reactivate">';
$b .= wp_nonce_field('newsletter-reactivate', '_wpnonce', true, false);
$b .= '<input type="hidden" name="nk" value="' . esc_attr($this->get_user_key($user)) . '">';
```
**Explanation:**
Similar to the first vulnerability, the reactivation form was missing CSRF protection. The fix adds a nonce field with a different action identifier (`newsletter-reactivate`) to protect against CSRF attacks on the reactivation endpoint.
---
## Vulnerability 3
**Vulnerability Existed:** yes
TRUE POSITIVE
**Missing CSRF Token Validation - CWE-352 - unsubscription.php lines 142-145**
**Old Code:**
```php
case 'uc':
$this->unsubscribe($user, $email);
```
**Fixed Code:**
```php
case 'uc':
$verified = wp_verify_nonce($_REQUEST['_wpnonce'], 'newsletter-unsubscribe');
if (!$verified) {
$this->redirect($this->build_action_url('u', $user, $email));
}
$this->unsubscribe($user, $email);
```
**Explanation:**
The server-side handler for the unsubscription action was not validating the nonce token. The fix adds verification using `wp_verify_nonce()` which matches the action identifier sent in the form. If verification fails, the request is redirected rather than processed, preventing CSRF attacks.
---
## Vulnerability 4
**Vulnerability Existed:** not sure
**Inconsistent CSRF Token Validation - CWE-352 - unsubscription.php lines 161-165**
**Old Code:**
```php
case 'reactivate':
$this->reactivate($user);
```
**Fixed Code:**
```php
case 'reactivate':
$verified = wp_verify_nonce($_REQUEST['_wpnonce'], 'newsletter-unsubscribe');
if (!$verified) {
die('Unverified request');
}
$this->reactivate($user);
```
**Explanation:**
The fix adds nonce validation for the reactivate endpoint, which is good for CSRF protection. However, there's a potential inconsistency: the nonce action name is `'newsletter-unsubscribe'` but the form uses `'newsletter-reactivate'`. This mismatch would cause verification to fail for valid reactivation requests. This appears to be a bug in the fix itself - the nonce action should be `'newsletter-reactivate'` to match the form.
---
## Vulnerability 5
**Vulnerability Existed:** yes
TRUE POSITIVE
**Missing CSRF Token in Email Links - CWE-352 - unsubscription.php lines 247-251**
**Old Code:**
```php
function hook_newsletter_replace($text, $user, $email, $html = true) {
if ($user) {
$text = $this->replace_url($text, 'unsubscription_confirm_url', $this->build_action_url('uc', $user, $email));
...
$text = $this->replace_url($text, 'reactivate_url', $this->build_action_url('reactivate', $user, $email));
```
**Fixed Code:**
```php
function hook_newsletter_replace($text, $user, $email, $html = true, $context = null) {
if ($user) {
$url = $this->build_action_url('uc', $user, $email);
if ('page' === $context) {
$url = wp_nonce_url($url, 'newsletter-unsubscribe');
}
$text = $this->replace_url($text, 'unsubscription_confirm_url', $url);
...
$url = $this->build_action_url('reactivate', $user, $email);
if ('page' === $context) {
$url = wp_nonce_url($url, 'newsletter-reactivate');
}
$text = $this->replace_url($text, 'reactivate_url', $url);
```
**Explanation:**
The fix adds contextual nonce protection for URLs embedded in pages. When the context is 'page', the URLs are passed through `wp_nonce_url()` which adds nonce parameters to the URLs. This protects against CSRF attacks when users click links in emails or pages. The fix correctly uses matching action identifiers with the forms.
CVE Analysis Results:
CVE-2026-1051: Yes
View CVE Description
The Newsletter – Send awesome emails from WordPress plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 9.1.0. This is due to missing or incorrect nonce validation on the hook_newsletter_action() function. This makes it possible for unauthenticated attackers to unsubscribe newsletter subscribers via a forged request granted they can trick a logged-in user into performing an action such as clicking on a link.
Showing 1 to 1 of 1 results