Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-71239

CVE-2026-71239: DjangoCRM Massmail XSS Vulnerability

CVE-2026-71239 is an XSS flaw in DjangoCRM's massmail module allowing template injection via unsanitized user input. Attackers can expose sensitive data and forge tokens. This post covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-71239 Overview

CVE-2026-71239 is a server-side template injection (SSTI) vulnerability in the DjangoCRM massmail module. The module renders user-controlled EmlMessage fields through Django's Template() constructor without sanitization. An authenticated user with mass-mail message edit rights can inject Django template syntax ({{ }} and {% %}) that executes at template render time.

Successful exploitation discloses other users' data and password hashes through request context variables, forges CSRF tokens, and includes arbitrary registered templates. The vulnerability is tracked under [CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine].

Critical Impact

Authenticated attackers with mass-mail edit rights can extract password hashes, forge CSRF tokens, and disclose sensitive request context data by injecting Django template expressions into email subject and content fields.

Affected Products

  • DjangoCRM massmail module — message_previews.py
  • DjangoCRM massmail module — email_creators.py
  • DjangoCRM massmail module — helpers.py

Discovery Timeline

  • 2026-08-05 - CVE-2026-71239 published to NVD
  • 2026-08-05 - Last updated in NVD database

Technical Details for CVE-2026-71239

Vulnerability Analysis

The massmail module treats attacker-controlled email fields as trusted template source. Three code paths reach Django's Template() constructor with unsanitized input from EmlMessage objects. message_previews.py builds an f-string that embeds message.subject and message.content directly into a Template() call. email_creators.py passes eml_message.subject as the template string argument to Template(). helpers.py repeats the same f-string interpolation pattern.

Django's Template class compiles its input into an executable node tree. Any {{ variable }} or {% tag %} sequence resolves against the current context at render time. Because the context contains request data, CSRF tokens, and user objects, injected expressions read authenticated session state belonging to recipients rather than the attacker.

Root Cause

The root cause is missing separation between template source and user data. The correct pattern renders a fixed template with the user content passed as a context variable, so template syntax in the data is treated as literal text. Instead, the affected code concatenates user data into the template source itself, which the engine then parses and executes.

Attack Vector

An authenticated user with permission to edit mass-mail messages sets EmlMessage.subject or EmlMessage.content to a payload containing Django template expressions. When another user previews the message or the mail dispatch pipeline renders it, the injected expressions execute in the server's rendering context. Attackers can enumerate context variables to reach user, request, and registered template loaders. Password hashes stored on the User model are reachable when the ORM object is present in context.

No verified public exploit code is available. See the DjangoCRM GitHub repository for source code and any pending fixes.

Detection Methods for CVE-2026-71239

Indicators of Compromise

  • EmlMessage records where subject or content contains {{, }}, {%, or %} sequences not consistent with normal marketing copy.
  • Rendered preview or outbound email bodies containing reflected values of csrf_token, request.user, password, or hash prefixes such as pbkdf2_sha256$.
  • Unusual read access by low-privilege accounts to mass-mail preview endpoints immediately after message edits.

Detection Strategies

  • Scan the massmail_emlmessage table for template metacharacters in subject and content columns.
  • Add application-level logging around calls to Template() in message_previews.py, email_creators.py, and helpers.py, capturing the rendered source string.
  • Alert on Django TemplateSyntaxError exceptions originating from the massmail module, which often accompany failed injection attempts.

Monitoring Recommendations

  • Monitor authenticated web requests to mass-mail preview and send endpoints for anomalous frequency by non-admin roles.
  • Correlate edits to EmlMessage objects with subsequent preview renders by different user sessions to detect targeting of specific victims.
  • Track outbound email content for template artifacts that indicate leaked context variables reaching recipients.

How to Mitigate CVE-2026-71239

Immediate Actions Required

  • Revoke massmail edit permissions from any account that does not require them, reducing the population of users able to inject payloads.
  • Audit existing EmlMessage records for template syntax and purge or sanitize any messages containing {{, }}, {%, or %}.
  • Disable the mass-mail preview and send workflows until a patched build is deployed if untrusted internal users hold edit rights.

Patch Information

No vendor advisory URL is listed in the NVD entry. Track the DjangoCRM GitHub repository for commits addressing message_previews.py, email_creators.py, and helpers.py. A correct fix renders a static template with user content passed as a context variable, for example replacing Template(f"...{message.content}...") with Template(fixed_source).render(Context({"content": message.content})).

Workarounds

  • Wrap all reads of EmlMessage.subject and EmlMessage.content with django.utils.html.escape before any template rendering path.
  • Replace direct Template(user_input) calls with rendering of a constant template that references user data through context variables only.
  • Restrict mass-mail edit rights to a small, trusted admin group through Django's permission system until the code is fixed.
bash
# Restrict massmail edit permission to a single admin group
python manage.py shell -c "
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
perm = Permission.objects.get(codename='change_emlmessage')
for g in Group.objects.exclude(name='massmail_admins'):
    g.permissions.remove(perm)
"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.