mirror of
https://github.com/django/django.git
synced 2025-01-03 15:06:09 +00:00
Refs #29708 -- Removed PickleSerializer per deprecation timeline.
This commit is contained in:
parent
23c8787439
commit
b119f4329c
@ -1,6 +1,3 @@
|
|||||||
# RemovedInDjango50Warning.
|
|
||||||
from django.core.serializers.base import PickleSerializer as BasePickleSerializer
|
|
||||||
from django.core.signing import JSONSerializer as BaseJSONSerializer
|
from django.core.signing import JSONSerializer as BaseJSONSerializer
|
||||||
|
|
||||||
JSONSerializer = BaseJSONSerializer
|
JSONSerializer = BaseJSONSerializer
|
||||||
PickleSerializer = BasePickleSerializer
|
|
||||||
|
@ -1,38 +1,14 @@
|
|||||||
"""
|
"""
|
||||||
Module for abstract serializer/unserializer base classes.
|
Module for abstract serializer/unserializer base classes.
|
||||||
"""
|
"""
|
||||||
import pickle
|
|
||||||
import warnings
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.deprecation import RemovedInDjango50Warning
|
|
||||||
|
|
||||||
DEFER_FIELD = object()
|
DEFER_FIELD = object()
|
||||||
|
|
||||||
|
|
||||||
class PickleSerializer:
|
|
||||||
"""
|
|
||||||
Simple wrapper around pickle to be used in signing.dumps()/loads() and
|
|
||||||
cache backends.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, protocol=None):
|
|
||||||
warnings.warn(
|
|
||||||
"PickleSerializer is deprecated due to its security risk. Use "
|
|
||||||
"JSONSerializer instead.",
|
|
||||||
RemovedInDjango50Warning,
|
|
||||||
)
|
|
||||||
self.protocol = pickle.HIGHEST_PROTOCOL if protocol is None else protocol
|
|
||||||
|
|
||||||
def dumps(self, obj):
|
|
||||||
return pickle.dumps(obj, self.protocol)
|
|
||||||
|
|
||||||
def loads(self, data):
|
|
||||||
return pickle.loads(data)
|
|
||||||
|
|
||||||
|
|
||||||
class SerializerDoesNotExist(KeyError):
|
class SerializerDoesNotExist(KeyError):
|
||||||
"""The requested serializer was not found."""
|
"""The requested serializer was not found."""
|
||||||
|
|
||||||
|
@ -317,3 +317,5 @@ to remove usage of these features.
|
|||||||
|
|
||||||
* The undocumented ability to pass ``errors=None`` to
|
* The undocumented ability to pass ``errors=None`` to
|
||||||
``SimpleTestCase.assertFormError()`` and ``assertFormsetError()`` is removed.
|
``SimpleTestCase.assertFormError()`` and ``assertFormsetError()`` is removed.
|
||||||
|
|
||||||
|
* ``django.contrib.sessions.serializers.PickleSerializer`` is removed.
|
||||||
|
@ -122,20 +122,6 @@ and the :setting:`SECRET_KEY` setting.
|
|||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
**If the** ``SECRET_KEY`` **or** ``SECRET_KEY_FALLBACKS`` **are not kept
|
|
||||||
secret and you are using the**
|
|
||||||
``django.contrib.sessions.serializers.PickleSerializer``, **this can lead
|
|
||||||
to arbitrary remote code execution.**
|
|
||||||
|
|
||||||
An attacker in possession of the :setting:`SECRET_KEY` or
|
|
||||||
:setting:`SECRET_KEY_FALLBACKS` can not only generate falsified session
|
|
||||||
data, which your site will trust, but also remotely execute arbitrary code,
|
|
||||||
as the data is serialized using pickle.
|
|
||||||
|
|
||||||
If you use cookie-based sessions, pay extra care that your secret key is
|
|
||||||
always kept completely secret, for any system which might be remotely
|
|
||||||
accessible.
|
|
||||||
|
|
||||||
**The session data is signed but not encrypted**
|
**The session data is signed but not encrypted**
|
||||||
|
|
||||||
When using the cookies backend the session data can be read by the client.
|
When using the cookies backend the session data can be read by the client.
|
||||||
@ -373,17 +359,6 @@ Bundled serializers
|
|||||||
See the :ref:`custom-serializers` section for more details on limitations
|
See the :ref:`custom-serializers` section for more details on limitations
|
||||||
of JSON serialization.
|
of JSON serialization.
|
||||||
|
|
||||||
.. class:: serializers.PickleSerializer
|
|
||||||
|
|
||||||
Supports arbitrary Python objects, but, as described above, can lead to a
|
|
||||||
remote code execution vulnerability if :setting:`SECRET_KEY` or any key of
|
|
||||||
:setting:`SECRET_KEY_FALLBACKS` becomes known by an attacker.
|
|
||||||
|
|
||||||
.. deprecated:: 4.1
|
|
||||||
|
|
||||||
Due to the risk of remote code execution, this serializer is deprecated
|
|
||||||
and will be removed in Django 5.0.
|
|
||||||
|
|
||||||
.. _custom-serializers:
|
.. _custom-serializers:
|
||||||
|
|
||||||
Write your own serializer
|
Write your own serializer
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.sessions.backends.db import SessionStore
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.test import TestCase, ignore_warnings, override_settings
|
from django.test import TestCase
|
||||||
from django.utils.deprecation import RemovedInDjango50Warning
|
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Base,
|
Base,
|
||||||
@ -106,29 +104,6 @@ class DeferRegressionTest(TestCase):
|
|||||||
list(SimpleItem.objects.annotate(Count("feature")).only("name")), list
|
list(SimpleItem.objects.annotate(Count("feature")).only("name")), list
|
||||||
)
|
)
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango50Warning)
|
|
||||||
@override_settings(
|
|
||||||
SESSION_SERIALIZER="django.contrib.sessions.serializers.PickleSerializer"
|
|
||||||
)
|
|
||||||
def test_ticket_12163(self):
|
|
||||||
# Test for #12163 - Pickling error saving session with unsaved model
|
|
||||||
# instances.
|
|
||||||
SESSION_KEY = "2b1189a188b44ad18c35e1baac6ceead"
|
|
||||||
|
|
||||||
item = Item()
|
|
||||||
item._deferred = False
|
|
||||||
s = SessionStore(SESSION_KEY)
|
|
||||||
s.clear()
|
|
||||||
s["item"] = item
|
|
||||||
s.save(must_create=True)
|
|
||||||
|
|
||||||
s = SessionStore(SESSION_KEY)
|
|
||||||
s.modified = True
|
|
||||||
s.save()
|
|
||||||
|
|
||||||
i2 = s["item"]
|
|
||||||
self.assertFalse(i2._deferred)
|
|
||||||
|
|
||||||
def test_ticket_16409(self):
|
def test_ticket_16409(self):
|
||||||
# Regression for #16409 - make sure defer() and only() work with annotate()
|
# Regression for #16409 - make sure defer() and only() work with annotate()
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import pickle
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from functools import partialmethod
|
from functools import partialmethod
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
@ -6,12 +5,11 @@ from unittest import mock, skipIf
|
|||||||
|
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
from django.core.serializers import SerializerDoesNotExist
|
from django.core.serializers import SerializerDoesNotExist
|
||||||
from django.core.serializers.base import PickleSerializer, ProgressBar
|
from django.core.serializers.base import ProgressBar
|
||||||
from django.db import connection, transaction
|
from django.db import connection, transaction
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.test import SimpleTestCase, override_settings, skipUnlessDBFeature
|
from django.test import SimpleTestCase, override_settings, skipUnlessDBFeature
|
||||||
from django.test.utils import Approximate, ignore_warnings
|
from django.test.utils import Approximate
|
||||||
from django.utils.deprecation import RemovedInDjango50Warning
|
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Actor,
|
Actor,
|
||||||
@ -487,31 +485,6 @@ class SerializersTransactionTestBase:
|
|||||||
self.assertEqual(art_obj.author.name, "Agnes")
|
self.assertEqual(art_obj.author.name, "Agnes")
|
||||||
|
|
||||||
|
|
||||||
class PickleSerializerTests(SimpleTestCase):
|
|
||||||
@ignore_warnings(category=RemovedInDjango50Warning)
|
|
||||||
def test_serializer_protocol(self):
|
|
||||||
serializer = PickleSerializer(protocol=3)
|
|
||||||
self.assertEqual(serializer.protocol, 3)
|
|
||||||
# If protocol is not provided, it defaults to pickle.HIGHEST_PROTOCOL
|
|
||||||
serializer = PickleSerializer()
|
|
||||||
self.assertEqual(serializer.protocol, pickle.HIGHEST_PROTOCOL)
|
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango50Warning)
|
|
||||||
def test_serializer_loads_dumps(self):
|
|
||||||
serializer = PickleSerializer()
|
|
||||||
test_data = "test data"
|
|
||||||
dump = serializer.dumps(test_data)
|
|
||||||
self.assertEqual(serializer.loads(dump), test_data)
|
|
||||||
|
|
||||||
def test_serializer_warning(self):
|
|
||||||
msg = (
|
|
||||||
"PickleSerializer is deprecated due to its security risk. Use "
|
|
||||||
"JSONSerializer instead."
|
|
||||||
)
|
|
||||||
with self.assertRaisesMessage(RemovedInDjango50Warning, msg):
|
|
||||||
PickleSerializer()
|
|
||||||
|
|
||||||
|
|
||||||
def register_tests(test_class, method_name, test_func, exclude=()):
|
def register_tests(test_class, method_name, test_func, exclude=()):
|
||||||
"""
|
"""
|
||||||
Dynamically create serializer tests to ensure that all registered
|
Dynamically create serializer tests to ensure that all registered
|
||||||
|
Loading…
Reference in New Issue
Block a user