Update dependency djangorestframework to v3.17.2 [SECURITY] - #86
Open
renovate[bot] wants to merge 1 commit into
Open
Update dependency djangorestframework to v3.17.2 [SECURITY]#86renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
==3.16.0→==3.17.2Django REST framework: Potential bypass of Django
DATA_UPLOAD_MAX_MEMORY_SIZEwhen parsing oversized JSON and urlencoded request bodies via DRFrequest.dataCVE-2026-73228 / GHSA-2m8g-3cmr-wg3w
More information
Details
Summary
While investigating Django REST Framework's request parsing behavior, I identified that DRF's high-level
request.dataparsing appears to bypass Django's configuredDATA_UPLOAD_MAX_MEMORY_SIZEprotection forapplication/jsonandapplication/x-www-form-urlencodedrequest bodies.In the tested configurations, Django correctly raises
RequestDataTooBigwhen applications accessrequest.bodyor Django's nativerequest.POST, but DRF successfully parses the same oversized payloads throughrequest.data.This behavior appears to occur because DRF passes the underlying
HttpRequestobject directly to parsers, which consume the request stream through Django's lower-level streaming interface rather than the guardedrequest.bodypath.I am reporting this privately because I am unsure whether this behavior is considered part of DRF's intended security boundary, but it appears to bypass a documented Django request-size protection for common DRF request parsing paths and may have availability implications.
What I Verified
I verified the behavior locally using the following combinations:
For both versions, the observed behavior was:
I also confirmed that:
multipart/form-dataremains protected because DRF delegates multipart parsing to Django's multipart parser.Technical Details
The relevant execution flow is:
The important implementation detail is that DRF assigns the original Django
HttpRequestobject as the parser stream.Unlike
request.bodyand Django's native form parsing, consuming the stream throughHttpRequest.read()does not trigger Django'sRequestDataTooBigprotection.As a result, DRF's built-in parsers successfully consume oversized request bodies that Django itself would reject through its higher-level request interfaces.
Reproduction Steps
Environment
Python 3.13
Django 6.0.7
Django REST Framework 3.17.1 (also reproduced on current upstream main)
Configure:
Create a simple DRF API view:
Start the application.
Send an oversized JSON request:
Example:
{ "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA..." }Observed:
Now compare against:
Observed:
Likewise, compare against:
using
Observed:
This demonstrates different enforcement depending on which request API is used.
Root Cause
Django documents
HttpRequest.read()as a streaming interface.DRF exposes
request.dataas the primary high-level request parsing API.Currently, DRF forwards the raw Django request stream directly to parsers before any request-size validation equivalent to Django's
request.bodypath occurs.Consequently:
fully consume oversized request bodies despite Django's configured request-size limit.
Security Impact
This does not appear to introduce:
However, it may reduce the effectiveness of deployments relying on Django's
DATA_UPLOAD_MAX_MEMORY_SIZEto limit request-body resource consumption.Potential consequences include:
request.dataThe practical impact depends on deployment configuration, including:
Memory Observations
During local testing I observed successful parsing of oversized request bodies despite the configured limit.
Representative measurements showed significantly increased memory allocation while parsing large JSON and urlencoded payloads.
I intentionally did not perform destructive concurrency testing or attempt to exhaust system resources.
Scope
Confirmed affected:
Confirmed not affected:
Suggested Fix Direction
One possible approach would be for DRF to enforce Django's configured
DATA_UPLOAD_MAX_MEMORY_SIZEbefore handing the raw request stream to parsers that fully materialize request bodies in memory.This would preserve Django's configured request-size protection for the common
request.dataAPI without requiring broader changes to Django's documented streaming interface.Versions Tested
Affected:
I did not perform a complete historical version bisect.
Disclosure
I have not publicly disclosed this behavior.
I am submitting it privately in accordance with the project's security policy because I am unsure whether maintainers consider this part of DRF's intended security boundary.
Note:
Thank you for taking the time to review this report.
If you determine that this behavior should be addressed, I would be happy to help investigate further, develop a fix, add regression tests, and submit a patch if you'd find that helpful.
I have experience as a Python/Django software engineer, security researcher, and open-source contributor, and I'd be glad to contribute if you think that would be useful.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:LReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Django REST framework: AdminRenderer may disclose GET-protected data when rendering invalid write requests
CVE-2026-73229 / GHSA-g47c-3xmw-q6m2
More information
Details
Summary
AdminRenderer may disclose data that would normally be protected by GET permissions when rendering a 400 Bad Request response for an invalid write request.
If a view allows POST (or another write method) but denies GET, an invalid request rendered through AdminRenderer can invoke the view's GET handler and include data from the GET representation in the generated HTML response.
This behavior appears to be specific to AdminRenderer and does not affect the normal JSON rendering path.
Details
While investigating the AdminRenderer rendering flow, I observed that invalid write requests are rendered by temporarily overriding the request method and invoking the view's GET handler:
This execution path differs from a normal GET request.
Under normal request processing, a GET request flows through:
However, during AdminRenderer rendering, the renderer directly invokes:
view.get(...)
A view whose permission class explicitly allowed POST but denied GET still executed its GET handler while rendering an invalid POST request through AdminRenderer.
As a result, data intended to be available only through an authorized GET request was included in the generated HTML response.
Proof of Concept
Using a standard ListCreateAPIView.
Permission class:
Expected Behaviour
Observed Behaviour
Tthe same behavior is shown using a minimal APIView implementation.
Observed results:
Generic view reproduction:
These observations indicate that direct GET requests are correctly denied, while the simulated GET used during AdminRenderer rendering can still retrieve the protected representation.
Impact
This issue may result in information disclosure when all of the following conditions are met:
AdminRenderer is enabled.
The client negotiates the HTML renderer (for example using Accept: text/html).
The application permits POST (or another write method).
GET requests are denied by the configured permission class.
The invalid write request returns 400 Bad Request.
The GET representation contains information that the requester would normally not be permitted to access.
This issue does not appear to affect:
JSON rendering
Standard API responses
Successful write requests
The behavior appears limited to the HTML rendering path used by AdminRenderer.
Suggested Fix
Possible approaches include:
Perform equivalent permission checks before executing the simulated GET request.
Avoid invoking view.get() when the corresponding GET request would not be permitted.
Fall back to rendering only serializer/form validation errors instead of retrieving the GET representation.
A regression test could create a permission class that allows POST while denying GET, then verify that an invalid POST rendered with AdminRenderer does not include data from the protected GET representation.
Environment
Repository:
encode/django-rest-frameworkBranch tested:
security-audit-drfCommit tested:
cf582fb58e9e5ffcc8ed78a2cb9aaa8f4865666aSeverity
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
encode/django-rest-framework (djangorestframework)
v3.17.2Compare Source
What's Changed
Bug fixes
AdminRendererby @browniebroke in #10012. Thanks, @zainnadeem786 for the report.DATA_UPLOAD_MAX_MEMORY_SIZEforrequest.dataparsing by @zainnadeem786 in #10013. Thanks, @zainnadeem786 for the report.Full Changelog: encode/django-rest-framework@3.17.1...3.17.2
v3.17.1Compare Source
What's Changed
Bug fixes
HTMLFormRendererwith emptydatetimevalues by @p-r-a-v-i-n in #9928Full Changelog: encode/django-rest-framework@3.17.0...3.17.1
v3.17.0Compare Source
What's Changed
Breaking changes
Features
DurationFieldby @sevdog in #8532@versioning_class(),@content_negotiation_class(),@metadata_class()for function-based views by @qqii in #9719violation_error_codeandviolation_error_messagefromUniqueConstraintinUniqueTogetherValidatorby @s-aleshin in #9766ipaddressobjects inJSONEncoderby @corenting in #9087BigIntegerto string by @HoodyH in #9775Bug fixes
Tokenoverwrite by @mahdirahimi1999 in #9754UniqueTogetherValidatorvalidation when condition references a read-only field by @ticosax in #9764default=Noneby @Genarito in #9790__init__.pyby @TheFunctionalGuy in #9799HTMLFormRendererto ensure a validdatetime-localformat by @mgaligniana in #9365MultipleChoiceFieldby @fbozhang in #9735Translations
Packaging
pyproject.tomlby @deronnax in #9056MANIFEST.intopyproject.tomlby @p-r-a-v-i-n in #9825Other changes
secretsmodule by @mahdirahimi1999 in #9760@api_viewby @kernelshard in #9821New Contributors
Full Changelog: encode/django-rest-framework@3.16.1...3.17.0
v3.16.1Compare Source
This release fixes a few bugs, clean-up some old code paths for unsupported Python versions and improve translations.
Minor changes
backports.zoneinfodependency and conditions on unsupported Python 3.8 and lower in #9681. Python versions prior to 3.9 were already unsupported so this isn't considered as a breaking change.Bug fixes
unique_togethervalidation withSerializerMethodFieldin #9712UniqueTogetherValidatorto handle fields withsourceattribute in #9688Translations
Documentation
drf-restwindand update outdated images inbrowsable-api.mdin #9680djangorestframework-guardian2todjangorestframework-guardianin #9734requestin serializer context when usingHyperlinkedModelSerializerin #9732Internal changes
pyupgradetopre-commithooks in #9682pytzis available in #9715New Contributors
Full Changelog: encode/django-rest-framework@3.16.0...3.16.1
Configuration
📅 Schedule: (in timezone Etc/UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.