CVE case study
CVE-2026-78867: Stored Cross-Site Scripting in django-crm Chat Messages
django-crm through commit 508e4dfe stores chat message content without sanitization, so an authenticated low-privilege CRM operator can send a message containing JavaScript that runs in the recipient's Django admin session when they open the chat. No fixed version was available at disclosure; the maintainer closed the private report without remediation.
- Weakness
- CWE-79
- Affected
- All versions through commit 508e4dfe (2026-06-29); no fixed release.
- Remediation state
- No fixed version at disclosure; the maintainer closed the private report
- Advisory published
- 4 Sep 2026
Official vectorCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
Why it matters
django-crm is an open-source customer relationship management application built on Django. It includes an internal chat feature that users exchange messages through inside the Django admin interface. Message content submitted to the chat form (the clean_content method in chat/forms/chatmessageform.py) is stored without sanitization, and the admin changelist column that displays it (ChatMessageAdmin.message in chat/site/chatmessageadmin.py) renders the stored value with mark_safe after passing it through linebreaks(), a helper that inserts paragraph markup but does not HTML-escape. As a result, any HTML or script contained in a message is emitted verbatim into the page instead of being neutralized by Django's normal template escaping.
An authenticated low-privilege CRM operator can send a chat message whose content is a crafted payload, for example an image tag with an onerror handler, to a chosen user. When that recipient opens the chat in their own admin session, the stored payload executes as JavaScript in their browser under their session. If the recipient is a superuser, the attacker gains script execution in the highest-privilege admin context, crossing the trust boundary from a limited operator account to full administrator control over the CRM. The submitted vector scores it 9.0, Critical (CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H).
The issue was reported through GitHub private vulnerability reporting under advisory GHSA-xc63-6253-wpxj, and the maintainer closed the report without remediation, which is why it was submitted to MITRE for a CVE. It is a distinct sink from the earlier email-subject XSS tracked as GHSA-fqgm: here the source is chat content and the sink is ChatMessageAdmin.message. The engineering lesson is that escaping has to happen at the sink; calling mark_safe on stored user input, even after a text transform such as linebreaks() that does not escape, reintroduces exactly the injection that Django's automatic template escaping is designed to prevent.