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

CVE-2026-90806: DjangoCRM Authorization Bypass Vulnerability

CVE-2026-90806 is an authorization bypass flaw in DjangoCRM django-crm affecting the BulkUpdateCasesView function. Attackers can exploit this remotely to bypass security controls. This article covers technical details, affected versions, impact assessment, and mitigation strategies.

Published:

CVE-2026-90806 Overview

CVE-2026-90806 is a missing authorization vulnerability [CWE-862] affecting DjangoCRM django-crm versions up to 1.2. The flaw resides in the BulkUpdateCasesView function within backend/cases/bulk_views.py, part of the Bulk Case Update component. An authenticated remote attacker with low privileges can manipulate bulk update requests to modify case records they should not have access to. The vulnerability was patched in version 1.3.0 through commit 799bb1210238f402c0c4948c8eedb6e61cd0c8d7. Because django-crm is deployed as a customer relationship management platform, unauthorized modifications can affect confidentiality and integrity of sales pipeline, ticket, and customer data.

Critical Impact

Authenticated users can bypass per-record access controls to update or alter cases belonging to other users through the bulk update endpoint.

Affected Products

  • DjangoCRM django-crm versions up to and including 1.2
  • Component: Bulk Case Update (backend/cases/bulk_views.py)
  • Fixed in: django-crm v1.3.0

Discovery Timeline

  • 2026-09-14 - CVE-2026-90806 published to NVD
  • 2026-09-14 - Last updated in NVD database

Technical Details for CVE-2026-90806

Vulnerability Analysis

The vulnerability originates in the BulkUpdateCasesView handler, which accepts a list of case IDs and a set of field updates from the client. The endpoint applies the requested changes without verifying that the calling user has write permission on each individual case referenced in the request. As a result, any authenticated low-privilege account can submit arbitrary case IDs and modify fields such as status, priority, assignee, or tags across records outside their authorization scope.

This pattern is a classic broken access control failure at the object level, where authentication is verified but object-level authorization is skipped inside the bulk processing loop. The Exploit Prediction Scoring System places this issue in a low probability band for near-term exploitation, though the network attack vector and low complexity make targeted abuse straightforward for anyone with access to the CRM.

Root Cause

The root cause is missing authorization enforcement inside the bulk update code path. The view iterates over supplied case identifiers and applies field mutations without a per-object permission check. The patch introduces backend gating so that only cases the caller may write are updated, and the remainder are returned as no_access in the response payload.

Attack Vector

Exploitation requires an authenticated session on the target django-crm instance. The attacker sends a crafted POST request to the /cases/bulk/update/ endpoint containing target case IDs and the fields to modify. Because the backend does not filter the supplied IDs by ownership or role, the mutation succeeds against records belonging to other users or tenants.

javascript
// Security patch in frontend/src/lib/server/v2/tickets.js (v1.3.0)
// Merge pull request #746 from Django-CRM/dev

/**
 * Bulk-update tickets. `fields` is a subset of
 * { status, priority, case_type, closed_on, assigned_to: string[], tags: string[] }.
 * The backend enforces per-case write access and the close gate, so this only
 * forwards; it never gates.
 * @param {{ cookies: any }} evt
 * @param {string[]} ids
 * @param {Record<string, any>} fields
 */
export async function bulkUpdateTickets({ cookies }, ids, fields) {
  return await apiRequest(
    '/cases/bulk/update/',
    { method: 'POST', body: { ids, fields } },
    { cookies }
  );
}

/**
 * Bulk soft-delete tickets. Backend deletes only those the caller may delete
 * (admin or creator) and reports the rest as no_access.
 * @param {{ cookies: any }} evt
 * @param {string[]} ids
 */
export async function bulkDeleteTickets({ cookies }, ids) {
  return await apiRequest('/cases/bulk/delete/', { method: 'POST', body: { ids } }, { cookies });
}

Source: GitHub Commit 799bb121

Detection Methods for CVE-2026-90806

Indicators of Compromise

  • Unusual POST requests to /cases/bulk/update/ or /cases/bulk/delete/ containing large arrays of case IDs from a single low-privileged account.
  • Case records showing unexpected changes to status, assigned_to, priority, or closed_on fields with an audit user who does not own the record.
  • Sudden bulk reassignment or status flipping of cases outside the actor's normal team scope.

Detection Strategies

  • Enable Django request logging and application-level audit logs on the cases application, and alert on bulk mutation endpoints invoked outside expected admin workflows.
  • Correlate application logs with authentication logs to identify accounts that begin issuing bulk update calls after credential compromise or role changes.
  • Baseline the normal ratio of single-case updates to bulk updates per user and flag statistical outliers.

Monitoring Recommendations

  • Ship django-crm application logs into a centralized log platform and retain audit history of case field changes with actor and prior-value metadata.
  • Monitor HTTP response payloads from patched v1.3.0 instances for no_access markers, which indicate attempted access to cases the caller cannot modify.
  • Track the ratio of 200 responses to bulk endpoints per authenticated session and alert on spikes.

How to Mitigate CVE-2026-90806

Immediate Actions Required

  • Upgrade django-crm to version 1.3.0 or later, which contains the fix in commit 799bb1210238f402c0c4948c8eedb6e61cd0c8d7.
  • Audit recent case modification history for unauthorized changes made by low-privileged accounts prior to patching.
  • Rotate credentials and review session tokens for any account that may have exploited the endpoint.

Patch Information

The vendor released django-crm v1.3.0 with backend-side per-case write access enforcement for bulk update and bulk delete operations. Review the GitHub Release v1.3.0, the GitHub Pull Request #746, and the GitHub Issue #745 for full context. Additional analysis is available at VulDB CVE-2026-90806.

Workarounds

  • If immediate upgrade is not possible, restrict access to the bulk update endpoint at the reverse proxy or WAF layer to trusted administrator source IPs.
  • Temporarily disable the Bulk Case Update UI and route bulk operations through admin-only tooling until v1.3.0 is deployed.
  • Reduce the blast radius by tightening role assignments so that only vetted accounts hold any write role on the cases module.
bash
# Example nginx restriction for the bulk endpoints until upgrade
location ~ ^/cases/bulk/(update|delete)/ {
    allow 10.0.0.0/24;   # admin subnet
    deny all;
    proxy_pass http://django_crm_upstream;
}

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

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.