CVE-2026-73229 Overview
CVE-2026-73229 is an information disclosure vulnerability in Django REST framework (DRF), a widely used toolkit for building Web APIs in Python. Versions prior to 3.17.2 contain a flaw in rest_framework/renderers.py where AdminRenderer.render() uses override_method() to simulate a GET request and directly invokes view.get() without calling view.check_permissions(). When a user submits an invalid write request (POST or PUT), the resulting 400 Bad Request HTML response can leak data from the GET representation that the requester is not authorized to access. The issue is fixed in version 3.17.2 [CWE-200].
Critical Impact
Authenticated users with write access to an endpoint can read GET-protected data via the browsable Admin UI by submitting invalid write requests, bypassing view-level permission checks.
Affected Products
- Django REST framework versions prior to 3.17.2
- Applications using AdminRenderer in DRF's browsable API
- Deployments exposing the admin renderer to users with restricted GET permissions
Discovery Timeline
- 2026-08-11 - CVE-2026-73229 published to NVD
- 2026-08-11 - Last updated in NVD database
Technical Details for CVE-2026-73229
Vulnerability Analysis
The vulnerability resides in DRF's AdminRenderer class, which powers the browsable admin-style API interface. When a user submits an invalid write request (POST, PUT), the renderer attempts to re-render the page with the resource's GET representation alongside validation errors. To do this, it wraps the request with override_method(view, request, 'GET') and invokes view.get() directly.
The defect is that view.check_permissions() is never called on the simulated GET request. DRF permissions are typically evaluated by the view dispatcher, not by direct method invocation. A user permitted to POST but not to GET a resource can therefore trigger the GET code path by submitting malformed write data, receiving the protected representation embedded in the 400 Bad Request HTML response.
Root Cause
The root cause is missing authorization enforcement on a simulated request path. AdminRenderer.render() bypasses DRF's standard permission pipeline by calling view.get() directly rather than dispatching through the framework's request handling machinery, which would normally invoke check_permissions() and check_object_permissions().
Attack Vector
An authenticated attacker with write-only access to an endpoint sends a POST or PUT request containing invalid data. When the response uses AdminRenderer (typically via content negotiation for text/html in the browsable API), the renderer executes the view's GET handler and returns the protected data embedded in the HTML error page.
self.error_title = {'POST': 'Create', 'PUT': 'Edit'}.get(request.method, 'Errors')
with override_method(view, request, 'GET') as request:
- response = view.get(request, *view.args, **view.kwargs)
- data = response.data
+ # Only simulate the GET request if the current user is
+ # actually permitted to perform it. Otherwise, we could leak
+ # data that GET permissions are meant to protect.
+ try:
+ view.check_permissions(request)
+ except exceptions.APIException:
+ # The user isn't permitted to perform the GET request, so
+ # we must not expose the data it would return. Render only
+ # the error data instead of the detail/list representation.
+ if not isinstance(data, dict):
+ data = {api_settings.NON_FIELD_ERRORS_KEY: data}
+ else:
+ response = view.get(request, *view.args, **view.kwargs)
+ data = response.data
template = loader.get_template(self.template)
context = self.get_context(data, accepted_media_type, renderer_context)
Source: GitHub commit 71f8194. The patch wraps the simulated GET invocation in a check_permissions() call and falls back to rendering only the error payload when permissions fail.
Detection Methods for CVE-2026-73229
Indicators of Compromise
- HTTP 400 responses with Content-Type: text/html returned by DRF endpoints that also contain serialized resource fields in the response body.
- Repeated malformed POST or PUT requests from authenticated users targeting endpoints that they lack GET permissions for.
- Application logs showing successful AdminRenderer rendering following permission-check failures on paired GET requests.
Detection Strategies
- Audit application access logs for users generating invalid write requests against endpoints where they have no read permission and correlate with 400 HTML responses.
- Statically scan Django projects for the vulnerable Django REST framework version by parsing requirements.txt, pyproject.toml, or the output of pip freeze for versions below 3.17.2.
- Instrument DRF views with logging around check_permissions() to identify anomalous permission-check patterns on write endpoints.
Monitoring Recommendations
- Enable verbose request logging for endpoints using AdminRenderer and forward logs to a centralized analytics platform for anomaly detection.
- Alert on authenticated sessions that generate high rates of 400 Bad Request responses against write endpoints.
- Track DRF version inventory across production and staging environments to confirm patch coverage.
How to Mitigate CVE-2026-73229
Immediate Actions Required
- Upgrade Django REST framework to version 3.17.2 or later using pip install --upgrade djangorestframework.
- Inventory all Django applications and identify those exposing AdminRenderer in DEFAULT_RENDERER_CLASSES or per-view renderer configurations.
- Review per-view permission classes to ensure GET, POST, and PUT permissions are explicitly and consistently defined.
Patch Information
The fix is available in Django REST framework 3.17.2. See the GitHub Release 3.17.2, the GHSA-g47c-3xmw-q6m2 security advisory, and Pull Request #10012 for full details. The patch adds a view.check_permissions() call before simulating the GET request and renders only the error payload when the user lacks GET permission.
Workarounds
- Remove AdminRenderer from DEFAULT_RENDERER_CLASSES and any per-view renderer_classes until upgrade is possible.
- Restrict browsable API access to trusted administrative users only via network controls or middleware.
- Ensure any view exposing write actions enforces identical or stricter permissions for GET operations on the same resource.
# Upgrade Django REST framework to the patched version
pip install --upgrade 'djangorestframework>=3.17.2'
# Verify installed version
python -c "import rest_framework; print(rest_framework.VERSION)"
# Temporary workaround: remove AdminRenderer from settings.py
# REST_FRAMEWORK = {
# 'DEFAULT_RENDERER_CLASSES': [
# 'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer',
# ],
# }
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

