summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Harris <timharris@Tims-MacBook-Air-2.local>2026-05-18 17:06:06 -0700
committerJacob Walls <jacobtylerwalls@gmail.com>2026-05-27 11:41:48 -0400
commit6e15ac8066312328de279e3e072667416c205bfc (patch)
treeb946a9c743a450a88d90f09b60e9390ac4cef053
parent7ae70e7504b98553ab3537be84f930ea7e28c3c9 (diff)
Fixed #36905 -- Deprecated the safe parameter of JSONResponse.
Peer frameworks have long since dropped their analogous checks for this vulnerability that was fixed in ES5.
-rw-r--r--django/http/response.py17
-rw-r--r--docs/ref/request-response.txt8
-rw-r--r--docs/releases/6.2.txt8
-rw-r--r--tests/httpwrappers/tests.py25
4 files changed, 46 insertions, 12 deletions
diff --git a/django/http/response.py b/django/http/response.py
index 12cf47b1c1..3b948d6eed 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -20,6 +20,10 @@ from django.core.serializers.json import DjangoJSONEncoder
from django.http.cookie import SimpleCookie
from django.utils import timezone
from django.utils.datastructures import CaseInsensitiveMapping
+from django.utils.deprecation import (
+ RemovedInDjango71Warning,
+ django_file_prefixes,
+)
from django.utils.encoding import iri_to_uri
from django.utils.functional import cached_property
from django.utils.http import (
@@ -755,10 +759,21 @@ class JsonResponse(HttpResponse):
self,
data,
encoder=DjangoJSONEncoder,
- safe=True,
+ # RemovedInDjango71Warning: Remove the safe parameter.
+ safe=None,
json_dumps_params=None,
**kwargs,
):
+ # RemovedInDjango71Warning.
+ if safe is None:
+ safe = False
+ else:
+ warnings.warn(
+ "The safe parameter is deprecated.",
+ category=RemovedInDjango71Warning,
+ skip_file_prefixes=django_file_prefixes(),
+ )
+ # RemovedInDjango71Warning.
if safe and not isinstance(data, dict):
raise TypeError(
"In order to allow non-dict objects to be serialized set the "
diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt
index 906da679c7..eebd0cd053 100644
--- a/docs/ref/request-response.txt
+++ b/docs/ref/request-response.txt
@@ -1281,6 +1281,14 @@ using non-dict objects in JSON-encoded response.
modern browsers implement ECMAScript 5 which removes this attack vector.
Therefore it is possible to disable this security precaution.
+.. versionchanged:: 6.2
+
+ In earlier versions, the ``safe`` parameter defaulted to ``True``.
+
+.. deprecated:: 6.2
+
+ The ``safe`` parameter is deprecated.
+
Changing the default JSON encoder
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/releases/6.2.txt b/docs/releases/6.2.txt
index ba9396313d..1193f7a84d 100644
--- a/docs/releases/6.2.txt
+++ b/docs/releases/6.2.txt
@@ -251,7 +251,10 @@ backends.
Miscellaneous
-------------
-* ...
+* To facilitate the deprecation of the ``safe`` parameter of
+ :class:`~django.http.JsonResponse`, it now defaults to ``False``, because the
+ pollution vulnerability in the ``Array`` prototype was fixed in
+ `ES5 <https://262.ecma-international.org/5.1/#sec-11.1.4>`_.
.. _deprecated-features-6.2:
@@ -261,4 +264,5 @@ Features deprecated in 6.2
Miscellaneous
-------------
-* ...
+* The ``safe`` parameter is deprecated from :class:`~django.http.JsonResponse`.
+ Omitting the argument is equivalent to the prior ``safe=False`` usage.
diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py
index 151088909c..e2eb9af30f 100644
--- a/tests/httpwrappers/tests.py
+++ b/tests/httpwrappers/tests.py
@@ -24,6 +24,7 @@ from django.http import (
parse_cookie,
)
from django.test import SimpleTestCase
+from django.utils.deprecation import RemovedInDjango71Warning
from django.utils.encoding import iri_to_uri
from django.utils.functional import lazystr
from django.utils.http import MAX_URL_REDIRECT_LENGTH
@@ -703,25 +704,31 @@ class JsonResponseTests(SimpleTestCase):
response = JsonResponse(data)
self.assertEqual(json.loads(response.text), data)
- def test_json_response_raises_type_error_with_default_setting(self):
- with self.assertRaisesMessage(
- TypeError,
- "In order to allow non-dict objects to be serialized set the "
- "safe parameter to False",
+ # RemovedInDjango71Warning: When the deprecation ends, remove this test.
+ def test_json_response_raises_type_error_with_safe_arg(self):
+ with (
+ self.assertRaisesMessage(
+ TypeError,
+ "In order to allow non-dict objects to be serialized set the "
+ "safe parameter to False",
+ ),
+ self.assertWarnsMessage(
+ RemovedInDjango71Warning, "The safe parameter is deprecated."
+ ),
):
- JsonResponse([1, 2, 3])
+ JsonResponse([1, 2, 3], safe=True)
def test_json_response_text(self):
- response = JsonResponse("foobar", safe=False)
+ response = JsonResponse("foobar")
self.assertEqual(json.loads(response.text), "foobar")
def test_json_response_list(self):
- response = JsonResponse(["foo", "bar"], safe=False)
+ response = JsonResponse(["foo", "bar"])
self.assertEqual(json.loads(response.text), ["foo", "bar"])
def test_json_response_uuid(self):
u = uuid.uuid4()
- response = JsonResponse(u, safe=False)
+ response = JsonResponse(u)
self.assertEqual(json.loads(response.text), str(u))
def test_json_response_custom_encoder(self):