Sceawere
Vulnerability Detail
CVE-2026-87975UPDATED Verified Sceawere Triage Sources: NVD / CISA KEV
Django FormSet Unauthorized Deletion Vulnerability
Vulnerability Metadata
- Severity
- Medium
- Score / CVSS
- 4.3
- Creation Date
- 11h ago
- Vendor
- djangoproject
- Product
- Django
- Attack Type
- CWE-639: Authorization Bypass Through User-Controlled Key
- Vector String
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
- Attack Complexity
- LOW
Narrative and Response
Description
An issue was discovered in Django 6.1 before 6.1.2, 6.0 before 6.0.9, and 5.2 before 5.2.18. `django.forms.models.BaseModelFormSet.save_existing_objects()` used the presence of a primary key on a submitted form's instance as evidence that the instance belonged to the formset's limiting queryset. An object outside that queryset is represented by a newly constructed instance whose primary key can still be populated from submitted data when the model's primary key is a field accepted by the form, such as a `OneToOneField` or parent link used as the primary key of an inline formset's model, or a natural or UUID primary key included in the form's fields. This allows an authenticated user permitted to submit such a formset to delete rows outside the limiting queryset, without any permission on the targeted object, via forged management-form data marking an out-of-queryset object for deletion. Models using the default AutoField primary key are not affected. Earlier, unsupported Django series (such as 5.1.x, 5.0.x, and 4.2.x) were not evaluated and may also be affected. Django would like to thank Seonggwon Yoon for reporting this issue.
Executive Summary
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Technical Details
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Mitigations
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
References
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Additional Metadata
{
"score": "4.3",
"pubDate": "2026-10-06T14:17:47.580Z",
"pubdate": "2026-10-06T14:17:47.580Z",
"executiveSummary": "A critical security vulnerability exists within Django's model formset processing logic, specifically affecting BaseModelFormSet.save_existing_objects().\nThe vulnerability allows an authenticated attacker to delete database records that fall outside of the authorized limiting queryset.\nThis flaw is primarily exploitable when models utilize custom primary keys (e.g., OneToOneField, UUID, or natural keys) that are exposed in form fields, as opposed to the default AutoField.\nBy manipulating the management-form data during a POST request, a malicious user can force the deletion of unauthorized records without holding explicit permissions for those specific objects.\nThis issue impacts Django versions 6.1 before 6.1.2, 6.0 before 6.0.9, and 5.2 before 5.2.18, with potential exposure in older, unsupported versions. The primary risk is unauthorized data loss and potential integrity compromise within applications utilizing inline formsets or custom primary key models.",
"technicalDetails": "The root cause of this vulnerability lies in an insecure validation mechanism within django.forms.models.BaseModelFormSet.save_existing_objects(). The implementation incorrectly relies on the existence of a primary key on a submitted form instance as sufficient verification that the instance resides within the intended, restricted limiting queryset.\nWhen a user submits a formset, the application logic assumes that any instance featuring a valid primary key is part of the query set restricted for that specific user or context. However, an attacker can supply forged data to populate the primary key of a newly constructed instance, even if that instance was not originally present in the limiting queryset.\nThis is particularly dangerous when the model primary key is a field explicitly included in the form fields, such as a OneToOneField or a parent link in an inline formset scenario, or when using UUIDs/natural keys. Because the system fails to verify the instance against the actual limiting queryset before processing deletion requests, it incorrectly assumes the attacker is interacting with a legitimate object in their scope.\nThe attack flow follows these steps: 1) An attacker identifies a formset view that permits row deletion and uses models with non-default primary keys; 2) The attacker crafts a request containing a forged management-form, marking an arbitrary record (the target) for deletion; 3) The attacker injects the target object's primary key into the submitted form data; 4) django.forms.models.BaseModelFormSet.save_existing_objects() processes the request, incorrectly identifies the target object as belonging to the valid queryset due to the presence of the manipulated primary key; 5) The framework proceeds to invoke the deletion routine on the unintended target object.\nModels utilizing the standard AutoField are immune, as the primary key is typically not user-controllable via submitted form data. The vulnerability requires the attacker to be authenticated, though they need not have direct permission to modify or delete the specific targeted row, effectively bypassing authorization controls provided by the framework's queryset limiting logic. The post-exploitation impact is unauthorized arbitrary record deletion, which could lead to significant data loss or disruption of application-specific business logic depending on the database schema."
}