DEV Community

CVE Reports
CVE Reports

Posted on • Originally published at cvereports.com

GHSA-JMR4-P576-V565: listmonk: From Humble Campaign Manager to Super Admin via XSS

listmonk: From Humble Campaign Manager to Super Admin via XSS

Vulnerability ID: GHSA-JMR4-P576-V565
CVSS Score: 5.4
Published: 2026-01-02

listmonk, a self-hosted newsletter manager, contains a classic Stored Cross-Site Scripting (XSS) vulnerability that allows a low-privileged user to achieve full administrative control. By embedding malicious JavaScript into a campaign or template, an attacker can execute code in a Super Admin's browser context. The vulnerability is made more severe by a 'no-click' attack vector through the public archive feature, where an admin simply visiting a link can trigger a full account takeover. The provided patch only partially addresses the issue, leaving a potential attack vector wide open.

TL;DR

A low-privilege user in listmonk can inject JavaScript into a campaign. When an admin views it, the script runs, silently creating a new admin account for the attacker. The fix patches the admin preview but explicitly leaves the public archive vector potentially vulnerable.


⚠️ Exploit Status: POC

Technical Details

  • CWE ID: CWE-79
  • CWE Name: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
  • Attack Vector: Network
  • Attack Complexity: Low
  • Privileges Required: Low (Campaign Management)
  • CVSS v4.0 Score: 5.4 (Medium)
  • Impact: Privilege Escalation to Super Admin, Account Takeover
  • Exploit Status: Proof-of-Concept
  • KEV Status: Not Listed

Affected Systems

  • listmonk
  • listmonk: < 6.0.0 (Fixed in: 6.0.0)

Code Analysis

Commit: 74dc5a0

Add sandboxing to campaign preview iframe. This addresses the specific security scenario described here: https://github.com/knadh/listmonk/security/advisories/GHSA-jmr4-p576-v565. Although it cannot mitigate a lower ranking user with campaign/template permissions adding arbitrary scripts to templates that render in various places including the public archive page.

File: frontend/src/components/CampaignPreview.vue
@@ -18,7 +18,7 @@
                   </form>

                   <iframe id="iframe" name="iframe" ref="iframe" :title="title" :src="isPost ? 'about:blank' : previewURL"
-            @load="onLoaded" />
+            @load="onLoaded" sandbox="allow-scripts" />
                 </section>
                 <footer class="modal-card-foot has-text-right">
                   <b-button @click="close">
@@ -61,6 +61,7 @@ export default {
                     return {
                       isVisible: true,
                       isLoading: true,
+              formSubmitted: false,
                     };
                   },

@@ -71,11 +72,15 @@ export default {
                     },

                     // On iframe load, kill the spinner.
-            onLoaded(l) {
-              if (l.srcElement.contentWindow.location.href === 'about:blank') {
+            onLoaded() {
+              if (!this.isPost) {
+                this.isLoading = false;
                             return;
+              }
+
+              if (this.formSubmitted) {
+                this.isLoading = false;
                       }
-              this.isLoading = false;
                     },
                   },

@@ -98,11 +103,12 @@ export default {
                   },

                   mounted() {
-            setTimeout(() => {
-              if (this.isPost) {
+            if (this.isPost) {
+              setTimeout(() => {
                             this.$refs.form.submit();
-              }
-            }, 100);
+                this.formSubmitted = true;
+              }, 100);
+            }
                   },
                 };
                 </script>
Enter fullscreen mode Exit fullscreen mode

Mitigation Strategies

  • Upgrade to listmonk version 6.0.0 or newer immediately.
  • Implement a strict, whitelist-based HTML sanitization library for all user-provided content before rendering.
  • Deploy a strong Content Security Policy (CSP) to block inline scripts and untrusted script sources.
  • Review and enforce the principle of least privilege for all user roles, especially those with content creation permissions.
  • Regularly audit campaign and template content for suspicious scripts or HTML.

Remediation Steps:

  1. Take the listmonk instance offline or place it in maintenance mode.
  2. Back up the application data and database.
  3. Follow the official listmonk documentation to upgrade to version 6.0.0 or the latest stable release.
  4. After upgrading, conduct a thorough audit of all user accounts, especially Super Admin accounts, to identify any unauthorized accounts created via this exploit.
  5. Review existing campaigns and templates for any malicious payloads and remove them.
  6. Bring the application back online and monitor logs for any suspicious activity.

References


Read the full report for GHSA-JMR4-P576-V565 on our website for more details including interactive diagrams and full exploit analysis.

Top comments (0)