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>
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:
- Take the listmonk instance offline or place it in maintenance mode.
- Back up the application data and database.
- Follow the official listmonk documentation to upgrade to version 6.0.0 or the latest stable release.
- After upgrading, conduct a thorough audit of all user accounts, especially Super Admin accounts, to identify any unauthorized accounts created via this exploit.
- Review existing campaigns and templates for any malicious payloads and remove them.
- 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)