CVE case study

CVE-2026-78865: Missing Authorization in django-crm User Transfer Grants Superoperator Rights

The user-transfer view in django-crm is gated only by login_required, so any authenticated low-privilege CRM operator can add their own account to a privileged role group and gain application-admin authority across departments. No fixed version was available at disclosure; the maintainer closed the private report without remediation.

Weakness
CWE-862, CWE-269
Affected
All versions up to and including commit 508e4dfe on the main branch (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:N/S:U/C:H/I:H/A:N

Why it matters

django-crm is an open-source customer-relationship-management application that organizes users into role groups such as operators, superoperators, and chiefs. The user-transfer view (common/views/user_transfer.py), wired into common/urls.py, is meant to move a user between departments, but it is protected only by Django's login_required decorator. The view rewrites a User object's group membership straight from raw POST parameters and never checks the caller's role, never confirms that the owner being edited is the caller, and never confirms that the supplied group is actually a department group. Those three missing checks are the root cause.

Because any logged-in account can reach the endpoint, a low-privilege operator can post a request that names their own account as the owner and names the id of a privileged group, for example superoperators or chiefs, as the target. The view happily adds the attacker to that group. On the next request, common/utils/usermiddleware.py derives the is_superoperator and is_chief flags from the group name, so the attacker holds cross-department application-admin authority. This is application-superuser-equivalent power, not the Django is_superuser bit, but within the CRM it crosses the trust boundary between an ordinary user and an administrator. The submitted vector scores it 8.1 (High).

The issue was reported to the maintainer through GitHub private vulnerability reporting under advisory GHSA-pfq8-h8c4-mprw. The maintainer closed the report without remediation, so it was submitted to MITRE and CVE-2026-78865 was assigned; no fixed version was available at disclosure. The engineering lesson is that a view that mutates authorization state must verify the caller's role and object ownership at the point of the write, because a login check alone establishes only that someone is authenticated, not that they are allowed to make the change.

References

Further reading

Evidence connected to this article.

Back to article start