Pickle can run code when it loads data, so a signed cookie session serialized with pickle turns any SECRET_KEY leak into remote code execution. Django recommends JSON serialization and removed django.contrib.sessions.serializers.PickleSerializer in Django 5.0. If you run an older project, check SESSION_SERIALIZER.
The attack scenario Django describes
Django's session documentation lays out the risk in plain terms. If you use the signed cookie session backend and SECRET_KEY, or any key in SECRET_KEY_FALLBACKS, is known to an attacker, then the attacker could insert a string into their session which, when unpickled, executes arbitrary code on the server. The docs add that the technique is simple and easily available on the internet, and that there is no inherent Django vulnerability that would leak the key.
The signature is meant to stop tampering. But the signature is only as strong as the key, and with pickle the consequence of a forged value is not a fake username, it is code running on your server. In other words, a SECRET_KEY leak immediately escalates to remote code execution.
What changed in Django 5.0
The Django 5.0 release notes list the removal of PickleSerializer under features removed after deprecation. Projects on 5.0 or later cannot select it. Projects on older, unsupported versions may still be using it, often through a line someone added years ago to store richer Python objects in the session.
What JSON gives up
JSON serialization only handles basic data types. The docs point out that JSON supports only string keys, so a session key of 0 comes back as "0", and data that is not valid UTF-8 cannot be stored. Types such as datetime and Decimal need conversion before you store them.
The docs describe this as a trade-off between convenience and security, and recommend sticking with JSON, especially with the cookie backend. If you write your own serializer, be careful that your decoder can reliably return what you stored.
| Choice | Convenience | Risk if the key leaks |
|---|---|---|
| JSON serializer | Basic types only | Forged session data, no code execution from the format |
| Pickle serializer (old versions) | Almost any Python object | Remote code execution |
| Server side session storage | Data stays off the client | Cookie holds only an ID |
A checklist for older projects
- Search settings for SESSION_SERIALIZER and any custom serializer class.
- If it points to PickleSerializer, plan the move to JSON. Sessions created with pickle will not load under JSON, so users will sign in again.
- Convert values in your code to JSON friendly types before putting them in request.session.
- Treat SECRET_KEY exposure as a code execution event on those versions and rotate promptly.
- Plan the upgrade. Old versions also miss security fixes.
The session docs also warn that cookie session data is signed but not encrypted, so a client can read what is in it. Keep sensitive values out of cookie-backed sessions regardless of serializer.
Other places pickle hides in Django
Django's cache documentation warns about file-based caching: someone who can write to the cache directory can falsify HTML content and also run arbitrary code, because the data is serialized with pickle. Keep cache directories writable only by the application user and out of any shared location.
Try it yourself
Click through it at your own pace, or open it full screen. Look for how unsafe deserialization calls are reported.
Quick check
Is pickle in sessions a Django bug?
No. Django says there is no inherent vulnerability involved. The risk appears only if the signing key is exposed.
Can I still use pickle on Django 5.0 or later?
The built-in PickleSerializer was removed in 5.0. Writing your own pickle based serializer would recreate the risk, so avoid it.
Safeguard's SAST, reachability analysis and dependency scanning can flag unsafe deserialization and unsupported Django versions. Run a free scan.
Sources
Last reviewed: 19 October 2026.