Django

Frameworks & Libraries

The web framework for perfectionists with deadlines.

Latest 6.1 · by Django Software FoundationWebsitePyPI · Django

Branches

6.1
6.1
5.2
5.2.17
6.0
6.0.8
4.2
4.2.30

Release activity

Release activity — 18 releases across 10 days since Mar 3, 2026. Each cell is one day; darker means more releases that day. Nothing is recorded before Mar 3, 2026. Older weeks are hidden at this screen width.
MayJunJulAug
SundayNo releases on May 3, 2026No releases on May 10, 2026No releases on May 17, 2026No releases on May 24, 2026No releases on May 31, 2026No releases on Jun 7, 2026No releases on Jun 14, 2026No releases on Jun 21, 2026No releases on Jun 28, 2026No releases on Jul 5, 2026No releases on Jul 12, 2026No releases on Jul 19, 2026No releases on Jul 26, 2026No releases on Aug 2, 2026No releases on Aug 9, 2026No releases on Aug 16, 2026
MondayNo releases on May 4, 2026No releases on May 11, 2026No releases on May 18, 2026No releases on May 25, 2026No releases on Jun 1, 2026No releases on Jun 8, 2026No releases on Jun 15, 2026No releases on Jun 22, 2026No releases on Jun 29, 2026No releases on Jul 6, 2026No releases on Jul 13, 2026No releases on Jul 20, 2026No releases on Jul 27, 2026No releases on Aug 3, 2026No releases on Aug 10, 2026No releases on Aug 17, 2026
Tuesday2 releases on May 5, 2026No releases on May 12, 2026No releases on May 19, 2026No releases on May 26, 2026No releases on Jun 2, 2026No releases on Jun 9, 2026No releases on Jun 16, 2026No releases on Jun 23, 2026No releases on Jun 30, 20262 releases on Jul 7, 2026No releases on Jul 14, 2026No releases on Jul 21, 2026No releases on Jul 28, 20262 releases on Aug 4, 2026No releases on Aug 11, 2026
WednesdayNo releases on May 6, 2026No releases on May 13, 20261 release on May 20, 2026No releases on May 27, 20262 releases on Jun 3, 2026No releases on Jun 10, 2026No releases on Jun 17, 20261 release on Jun 24, 2026No releases on Jul 1, 2026No releases on Jul 8, 2026No releases on Jul 15, 20261 release on Jul 22, 2026No releases on Jul 29, 20261 release on Aug 5, 2026No releases on Aug 12, 2026
ThursdayNo releases on May 7, 2026No releases on May 14, 2026No releases on May 21, 2026No releases on May 28, 2026No releases on Jun 4, 2026No releases on Jun 11, 2026No releases on Jun 18, 2026No releases on Jun 25, 2026No releases on Jul 2, 2026No releases on Jul 9, 2026No releases on Jul 16, 2026No releases on Jul 23, 2026No releases on Jul 30, 2026No releases on Aug 6, 2026No releases on Aug 13, 2026
FridayNo releases on May 8, 2026No releases on May 15, 2026No releases on May 22, 2026No releases on May 29, 2026No releases on Jun 5, 2026No releases on Jun 12, 2026No releases on Jun 19, 2026No releases on Jun 26, 2026No releases on Jul 3, 2026No releases on Jul 10, 2026No releases on Jul 17, 2026No releases on Jul 24, 2026No releases on Jul 31, 2026No releases on Aug 7, 2026No releases on Aug 14, 2026
SaturdayNo releases on May 9, 2026No releases on May 16, 2026No releases on May 23, 2026No releases on May 30, 2026No releases on Jun 6, 2026No releases on Jun 13, 2026No releases on Jun 20, 2026No releases on Jun 27, 2026No releases on Jul 4, 2026No releases on Jul 11, 2026No releases on Jul 18, 2026No releases on Jul 25, 2026No releases on Aug 1, 2026No releases on Aug 8, 2026No releases on Aug 15, 2026

18 releases since Mar 3, 2026, busiest day 3

Changelog

Filter releases by branch
18 of 18 releases

6.1

Latest
Added 14
  • Model field fetch modes allow configurable on-demand fetching behavior with FETCH_ONE, FETCH_PEERS, and FETCH_RAISE modes via QuerySet.fetch_mode()
  • ForeignKey.on_delete now supports database-level delete options DB_CASCADE, DB_SET_NULL, and DB_SET_DEFAULT using SQL ON DELETE clause
  • New MAILERS setting supports configuring multiple email backends with different options
  • Admin site login view now redirects authenticated users to the next URL if available
  • Admin FilteredSelectMultiple widget now uses optgroups to preserve named groups
  • Admin change list now selects only foreign key fields specified in list_display instead of all foreign key fields when list_select_related is False
Changed 1
  • Default iteration count for PBKDF2 password hasher increased from 1,200,000 to 1,500,000
Deprecated 1
  • EMAIL_BACKEND and related EMAIL_* settings will be replaced by MAILERS in Django 7.0 and now issue deprecation warnings

Django 6.1 release notes

August 5, 2026 Welcome to Django 6.1! These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 6.0 or earlier. We’ve begun the deprecation process for some features. See the How to upgrade Django to a newer version guide if you’re updating an existing project. Mainstream support is expected to end in April 2027. Extended support is expected to end in December 2027.

Python compatibility

Django 6.1 supports Python 3.12, 3.13, and 3.14. We highly recommend, and only officially support, the latest release of each series.

What’s new in Django 6.1
Model field fetch modes

The on-demand fetching behavior of model fields is now configurable with fetch modes. These modes allow you to control how Django fetches data from the database when an unfetched field is accessed. Django provides three fetch modes:

  • FETCH_ONE, the default, fetches the missing field for the current instance only. This mode represents Django’s existing behavior.
  • FETCH_PEERS fetches a missing field for all instances that came from the same QuerySet. This mode works like an on-demand prefetch_related(). It can reduce most cases of the “N+1 queries problem” to two queries without any work to maintain a list of fields to prefetch.
  • FETCH_RAISE raises a FieldFetchBlocked exception. This mode can prevent unintentional queries in performance-critical sections of code. Use the new method QuerySet.fetch_mode() to set the fetch mode for model instances fetched by the QuerySet: from django.db import models books = Book.objects.fetch_mode(models.FETCH_PEERS) for book in books: print(book.author.name) Despite the loop accessing the author foreign key on each instance, the FETCH_PEERS fetch mode will make the above example perform only two queries:
  • Fetch all books.
  • Fetch associated authors. See fetch modes for more details.
Database-level delete options for ForeignKey.on_delete

ForeignKey.on_delete now supports database-level delete options:

  • DB_CASCADE
  • DB_SET_NULL
  • DB_SET_DEFAULT These options handle deletion logic entirely within the database, using the SQL ON DELETE clause. They are thus more efficient than the existing Python-level options, as Django does not need to load objects before deleting them. As a consequence, the DB_CASCADE option does not trigger the pre_delete or post_delete signals.
Mailers

The new MAILERS setting supports configuring multiple email backends with different options, similar to existing mechanisms for CACHES, DATABASES, STORAGES, and TASKS: MAILERS = { "default": { "BACKEND": "django.core.mail.backends.smtp.EmailBackend", "OPTIONS": {"host": "smtp.example.com", "use_tls": True}, }, "marketing": { "BACKEND": "example.third.party.EmailBackend", "OPTIONS": {"region": "africa-1"}, }, } You can select a mailer with the new using argument to email sending functions, or obtain an email backend instance with mail.mailers[alias]. See Sending email for more details. MAILERS is not yet enabled by default in existing projects. It will replace EMAIL_BACKEND and related EMAIL_* settings in Django 7.0. Until then, the older settings will continue to work but will issue deprecation warnings: see the list of email deprecations below. You can opt into the new feature at any time before Django 7.0; see Migrating email to mailers. To ease the transition, mail.mailers["default"] works with either MAILERS or the deprecated EMAIL_BACKEND setting defined. The deprecated get_connection() function will also return an instance of the default mailer when MAILERS is defined.

Minor features
django.contrib.admin
  • The admin site login view now redirects authenticated users to the next URL, if available, instead of always redirecting to the admin index page.
  • The admin’s FilteredSelectMultiple widget now uses s to preserve named groups (e.g. choices=[("Group", [("1", "Item")]), ...]).
  • When ModelAdmin.list_select_related is False (the default), the change list now selects only the foreign key fields specified in ModelAdmin.list_display, rather than all foreign key fields. This should improve performance for models with many foreign key fields.
  • The delete_confirmation_max_display option allows customizing how many objects are displayed on admin delete confirmation pages and inline protected deletion errors before the remainder is truncated. The default is None (no truncation).
  • In order to improve accessibility of the admin change forms:
  • Form fields are now shown below their respective labels instead of next to them.
  • Help text is now shown after the field label and before the field input.
  • Validation errors are now shown after the help text and before the field input.
  • Checkboxes are an exception to the above changes and continue to be displayed in their original layout.
  • list_display now uses boolean icons for boolean fields on related models.
  • The new location keyword argument of the action() decorator specifies which admin views the action is available on. The action is available on the admin change list page by default. It can also be available on the admin change form. See Controlling where actions are available for details.
  • The new description_plural keyword argument of the action() decorator specifies a human-readable description for actions on the admin change list page. Defaults to the description value. This is useful when the action is available on both the admin change list and admin change form.
django.contrib.auth
  • The default iteration count for the PBKDF2 password hasher is increased from 1,200,000 to 1,500,000.
  • Permission.name and Permission.codename values are now renamed when renaming models via a migration.
  • The new Permission.user_perm_str property returns the string suitable to use with User.has_perm().
django.contrib.gis
  • The isempty lookup and IsEmpty() database function are now supported on SpatiaLite.
  • The new num_dimensions lookup and NumDimensions() database function allow filtering geometries by the number of dimensions on PostGIS and SpatiaLite.
  • OpenLayersWidget is now based on OpenLayers 10.9.0 (previously 7.2.2).
django.contrib.postgres
  • inspectdb now introspects HStoreField when psycopg 3.2+ is installed and django.contrib.postgres is in INSTALLED_APPS.
  • ExclusionConstraint now supports the Hash index type.
django.contrib.sessions
  • SessionBase now supports boolean evaluation via bool().
CSP
  • The new csp_nonce_attr template tag renders the CSP nonce attribute on and elements, or renders a Media object’s assets with the nonce applied, when the csp() context processor is configured. See Nonce usage for details.
  • A new security.W027 system check warns when ContentSecurityPolicyMiddleware is enabled with CSP.NONCE in a CSP policy but django.template.context_processors.csp is not configured.
  • CSP nonce attributes are now added on , , and elements in admin templates and all built-in templates when the csp() context processor is configured. See Nonce config for setup instructions.
Email
  • A new mail.E001 deployment-only system check prevents using one of Django’s email backends that is not intended for production use in the 'default' MAILERS entry.
  • A new mail.W001 system check warns when MAILERS is defined but does not include a 'default' entry.
Forms
  • The new asset object Stylesheet is available for adding custom HTML-attributes to stylesheet links in form media. See paths as objects for more details.
  • The new constant django.db.models.fields.BLANK_CHOICE_LABEL defines a more accessible and translatable default label for the blank choice in forms, which is appended to most choices lists. The transitional setting USE_BLANK_CHOICE_DASH allows you to revert back to the old default label.
  • FilePathField now provides a set_choices() method to scan the directory at path and refresh the field’s choices. This allows per-request refreshing when called in a form’s init().
Generic Views
  • The new RedirectView.preserve_request attribute allows preserving the HTTP method and body during redirects, using 307/308 status codes instead of 302/301.
Management Commands
  • Management commands now set ArgumentParser's suggest_on_error argument to True by default on Python 3.14, enabling suggestions for incorrectly typed subcommand names and argument choices.
  • The loaddata command now calls m2m_changed signals with raw=True when loading fixtures.
  • The sendtestemail command now supports a --using option to specify the MAILERS alias.
Models
  • QuerySet.in_bulk() now supports chaining after QuerySet.values() and QuerySet.values_list().
  • The new JSONNull expression provides an explicit way to represent the JSON scalar null. It can be used when saving a top-level JSONField value, or querying for top-level or nested JSON null values. See Storing and querying for None for usage examples and some caveats.
  • DecimalField.max_digits and DecimalField.decimal_places are no longer required to be set on Oracle, PostgreSQL, and SQLite.
  • JSONField now supports negative array indexing on Oracle 21c+.
  • The new UUID4 and UUID7 database functions were added.
  • GeneratedField now supports virtual columns (db_persist set to False) on Postgres 18+ and stored columns (db_persist set to True) on Oracle 23ai/26ai (23.7+).
  • The m2m_changed signal now receives a raw argument.
  • StringAgg now supports distinct=True on SQLite when using the default delimiter Value(",") only.
  • The new QuerySet.totally_ordered property returns True if the QuerySet is ordered and the ordering is deterministic.
  • The new BitAnd, BitOr, and BitXor aggregates return the bitwise AND, OR, XOR, respectively. These aggregates were previously included only in contrib.postgres.
  • django.db.models.BinaryField now validates Base64 input strictly. Invalid Base64 strings now raise ValidationError instead of being silently accepted.
Requests and Responses
  • HttpRequest.multipart_parser_class can now be customized to use a different multipart parser class.
  • HttpResponseRedirect (and its subclasses), as well as the redirect() shortcut, now accept a max_length parameter to override the default maximum URL length limit.
Security
  • Signed cookies now use an unambiguous salt derivation by default. Set SIGNED_COOKIE_LEGACY_SALT_FALLBACK to True to continue accepting legacy signed cookies.
Serialization
  • Subclasses of models defining the natural_key() method can now opt out of natural key serialization by overriding the method to return an empty tuple: (). This ensures primary keys are serialized when using dumpdata --natural-primary.
  • The XML deserializer now raises SuspiciousOperation when it encounters unexpected nested tags.
Tasks
  • The task() decorator now accepts **kwargs, which are forwarded to the backend’s task_class.
  • Task and TaskResult instances can now be pickled and unpickled.
Tests
  • assertContains() and assertNotContains() can now be called multiple times on the same StreamingHttpResponse. Previously, they would consume the streaming response’s content, causing subsequent calls to fail.
Utilities
  • parse_duration() now supports ISO 8601 time periods expressed in weeks (PnW).
Backwards incompatible changes in 6.1
Database backend API

This section describes changes that may be needed in third-party database backends.

  • The DatabaseOperations.adapt_durationfield_value() hook is added. If the database has native support for DurationField, override this method to simply return the value.
  • The DatabaseIntrospection.get_relations() should now return a dictionary with 3-tuples containing (field_name_other_table, other_table, db_on_delete) as values. db_on_delete is one of the database-level delete options e.g. DB_CASCADE.
  • Set the new DatabaseFeatures.supports_inspectdb attribute to False if the management command isn’t supported. …
View originalPermalink
How 6.1 went

5.2.17

Added 1
  • Add max_geom_collections argument to GEOSGeometry, GeometryField form field, and model field to customize the geometry collection depth limit
Security 4
  • Disallow dict and non-valid GEOSGeometry str values in spatial lookups to prevent server-side file-write, remote code execution, and request forgery via spatial lookups (CVE-2026-15307)
  • Reject language codes longer than 500 characters in check_for_language() to mitigate denial-of-service attacks (CVE-2026-15337)
  • Enforce a maximum depth of 198 GEOMETRYCOLLECTIONs in well-known text format and a maximum of 198 total GEOMETRYCOLLECTIONs in well-known binary format to prevent denial-of-service attacks via nested geometry collections (CVE-2026-15830)
  • Validate URLField values using URLValidator before rendering as clickable links in the admin to prevent cross-site scripting (CVE-2026-15920)

Django 5.2.17 release notes

August 4, 2026 Django 5.2.17 fixes one security issue with severity “high”, two security issues with severity “moderate”, and one security issue with severity “low” in 5.2.16.

CVE-2026-15307: Server-side file-write and request forgery via spatial lookups

Spatial lookups allowed str and dict lookup values to be passed to GDALRaster when they represented rasters. Depending on the raster driver, this could write a file to disk (in some cases enabling remote code execution) or issue a network request as the Django process user. Because the admin changelist permits filtering via lookup_allowed(), the flaw was reachable by staff users with view permission on any registered model containing a spatial field. The following types are now disallowed by spatial lookups:

  • dict
  • A str that is not a valid GEOSGeometry, e.g. a serialized dictionary This is a backward incompatible change. As a reminder, all untrusted user input should be validated before use. For that reason, assignments to model fields are unaffected and still accept these input types. For guidance on how to keep using these types in spatial lookups, on validating untrusted input, and on further security considerations, see raster security considerations. This issue has severity “high” according to the Django security policy.
CVE-2026-15337: Potential denial-of-service vulnerability in check_for_language()

check_for_language() was subject to a potential denial-of-service attack when checking many distinct, very long language codes. Each code was used as a key in an in-memory cache, consuming process memory. The language value reaches this function through the django.views.i18n.set_language() view (not active by default) from POST data. Since request data is limited by DATA_UPLOAD_MAX_MEMORY_SIZE and the cache is configured to store a maximum number of entries, the memory that could be consumed was bounded. To mitigate this vulnerability, language codes longer than 500 characters are now rejected before the cached lookup. This issue has severity “low” according to the Django security policy.

CVE-2026-15830: Potential denial-of-service vulnerability via nested geometry collections

GEOSGeometry was subject to a potential denial-of-service attack when provided deeply nested GEOMETRYCOLLECTION objects, leading to a segmentation fault in GEOS. A maximum depth of 198 GEOMETRYCOLLECTIONs is now enforced for the well-known text (WKT) format, and a maximum number of 198 GEOMETRYCOLLECTIONs in total (breadth and depth) is enforced for well-known binary (WKB). Lookups against spatial fields and the GeometryField form field were also affected. The limit can be customized through the new max_geom_collections argument, available on GEOSGeometry, the form field, and the model field. The limit is not applied to GeoJSON inputs, as they were parsed by GDAL and are not affected. This issue has severity “moderate” according to the Django security policy.

CVE-2026-15920: Potential cross-site scripting via URLField values in the admin

The admin renders URLField values as clickable links on changelist views and read-only fields. The link was generated without validating the value as a safe URL, so a stored value using a potentially dangerous scheme was rendered as a link. URLField values shown via display_for_field are now validated using URLValidator before a link is rendered, and displayed as plain text if validation is failed. This issue has severity “moderate” according to the Django security policy.

View originalPermalink
How 5.2.17 went

6.0.8

Added 1
  • Add max_geom_collections argument to GEOSGeometry, form field, and model field to customize geometry collection limits
Changed 1
  • Add compatibility for sqlparse 0.5.5
Fixed 1
  • Fix regression in Django 6.0 where bulk_create() crashed on databases supporting returning rows from bulk inserts when a related object providing the primary key was saved after assignment
Security 4
  • Disallow dict and non-GEOSGeometry str types in spatial lookups to prevent server-side file-write, remote code execution, and request forgery via spatial lookups (CVE-2026-15307)
  • Reject language codes longer than 500 characters in check_for_language() to mitigate potential denial-of-service attack (CVE-2026-15337)
  • Enforce maximum depth of 198 GEOMETRYCOLLECTIONs in well-known text format and maximum of 198 total GEOMETRYCOLLECTIONs in well-known binary format to prevent denial-of-service via nested geometry collections (CVE-2026-15830)
  • Validate URLField values using URLValidator before rendering as links in admin changelist views and read-only fields to prevent cross-site scripting (CVE-2026-15920)

Django 6.0.8 release notes

August 4, 2026 Django 6.0.8 fixes one security issue with severity “high”, two security issues with severity “moderate”, one security issue with severity “low”, and several bugs in 6.0.7.

CVE-2026-15307: Server-side file-write and request forgery via spatial lookups

Spatial lookups allowed str and dict lookup values to be passed to GDALRaster when they represented rasters. Depending on the raster driver, this could write a file to disk (in some cases enabling remote code execution) or issue a network request as the Django process user. Because the admin changelist permits filtering via lookup_allowed(), the flaw was reachable by staff users with view permission on any registered model containing a spatial field. The following types are now disallowed by spatial lookups:

  • dict
  • A str that is not a valid GEOSGeometry, e.g. a serialized dictionary This is a backward incompatible change. As a reminder, all untrusted user input should be validated before use. For that reason, assignments to model fields are unaffected and still accept these input types. For guidance on how to keep using these types in spatial lookups, on validating untrusted input, and on further security considerations, see raster security considerations. This issue has severity “high” according to the Django security policy.
CVE-2026-15337: Potential denial-of-service vulnerability in check_for_language()

check_for_language() was subject to a potential denial-of-service attack when checking many distinct, very long language codes. Each code was used as a key in an in-memory cache, consuming process memory. The language value reaches this function through the django.views.i18n.set_language() view (not active by default) from POST data. Since request data is limited by DATA_UPLOAD_MAX_MEMORY_SIZE and the cache is configured to store a maximum number of entries, the memory that could be consumed was bounded. To mitigate this vulnerability, language codes longer than 500 characters are now rejected before the cached lookup. This issue has severity “low” according to the Django security policy.

CVE-2026-15830: Potential denial-of-service vulnerability via nested geometry collections

GEOSGeometry was subject to a potential denial-of-service attack when provided deeply nested GEOMETRYCOLLECTION objects, leading to a segmentation fault in GEOS. A maximum depth of 198 GEOMETRYCOLLECTIONs is now enforced for the well-known text (WKT) format, and a maximum number of 198 GEOMETRYCOLLECTIONs in total (breadth and depth) is enforced for well-known binary (WKB). Lookups against spatial fields and the GeometryField form field were also affected. The limit can be customized through the new max_geom_collections argument, available on GEOSGeometry, the form field, and the model field. The limit is not applied to GeoJSON inputs, as they were parsed by GDAL and are not affected. This issue has severity “moderate” according to the Django security policy.

CVE-2026-15920: Potential cross-site scripting via URLField values in the admin

The admin renders URLField values as clickable links on changelist views and read-only fields. The link was generated without validating the value as a safe URL, so a stored value using a potentially dangerous scheme was rendered as a link. URLField values shown via display_for_field are now validated using URLValidator before a link is rendered, and displayed as plain text if validation is failed. This issue has severity “moderate” according to the Django security policy.

Bugfixes
  • Fixed a regression in Django 6.0 that caused bulk_create() to crash on databases that support returning rows from bulk inserts when a related object providing the primary key was saved after assignment (#37234).
  • Added compatibility for sqlparse 0.5.5 (#37235).
View originalPermalink
How 6.0.8 went

5.2.16

Security 3
  • Fixed potential exposure of private data via cached Set-Cookie response in UpdateCacheMiddleware and cache_page() when requests carried unrelated cookies
  • Fixed heap buffer over-read in GDALRaster when instantiated with a bytes object representing a raster file
  • Fixed header injection possibility in DomainNameValidator by rejecting newlines in domain names

Django 5.2.16 release notes

July 7, 2026 Django 5.2.16 fixes three security issues with severity “low” in 5.2.15.

CVE-2026-48588: Potential exposure of private data via cached Set-Cookie response

UpdateCacheMiddleware and cache_page() avoided caching responses that set a cookie while varying on Cookie only when the incoming request contained no cookies at all. When the request already carried an unrelated cookie (such as a language or theme preference cookie), the protection did not apply, allowing a response that sets a session or other sensitive cookie to be stored in Django’s shared cache. This issue has severity “low” according to the Django security policy.

CVE-2026-53877: Heap buffer over-read in GDALRaster

When GDALRaster was instantiated with a bytes object representing a raster file, the vsi_buffer property could over-read the allocated buffer by approximately 32 bytes. This could result in information disclosure of adjacent heap memory or, in rare cases, a segmentation fault. Only rasters stored in GDAL’s virtual filesystem were affected. This issue has severity “low” according to the Django security policy.

CVE-2026-53878: Header injection possibility since DomainNameValidator accepted newlines in input

DomainNameValidator accepted newlines in domain names. If such values were included in HTTP responses, header injection attacks were possible. Django itself wasn’t vulnerable because HttpResponse prohibits newlines in HTTP headers. The vulnerability only affected uses of DomainNameValidator outside Django form fields, as CharField strips newlines by default. This issue has severity “low” according to the Django security policy.

View originalPermalink
How 5.2.16 went

6.0.7

Fixed 1
  • Fixed a regression in Django 6.0 where the PBKDF2 and MD5 password hashers raised UnicodeDecodeError for bytes passwords that were not valid UTF-8
Security 3
  • Fixed potential exposure of private data via cached Set-Cookie response in UpdateCacheMiddleware and cache_page() when requests contained unrelated cookies
  • Fixed heap buffer over-read in GDALRaster when instantiated with a bytes object representing a raster file
  • Fixed header injection possibility in DomainNameValidator by rejecting newlines in domain names

Django 6.0.7 release notes

July 7, 2026 Django 6.0.7 fixes three security issues with severity “low” and one bug in 6.0.6.

CVE-2026-48588: Potential exposure of private data via cached Set-Cookie response

UpdateCacheMiddleware and cache_page() avoided caching responses that set a cookie while varying on Cookie only when the incoming request contained no cookies at all. When the request already carried an unrelated cookie (such as a language or theme preference cookie), the protection did not apply, allowing a response that sets a session or other sensitive cookie to be stored in Django’s shared cache. This issue has severity “low” according to the Django security policy.

CVE-2026-53877: Heap buffer over-read in GDALRaster

When GDALRaster was instantiated with a bytes object representing a raster file, the vsi_buffer property could over-read the allocated buffer by approximately 32 bytes. This could result in information disclosure of adjacent heap memory or, in rare cases, a segmentation fault. Only rasters stored in GDAL’s virtual filesystem were affected. This issue has severity “low” according to the Django security policy.

CVE-2026-53878: Header injection possibility since DomainNameValidator accepted newlines in input

DomainNameValidator accepted newlines in domain names. If such values were included in HTTP responses, header injection attacks were possible. Django itself wasn’t vulnerable because HttpResponse prohibits newlines in HTTP headers. The vulnerability only affected uses of DomainNameValidator outside Django form fields, as CharField strips newlines by default. This issue has severity “low” according to the Django security policy.

Bugfixes
  • Fixed a regression in Django 6.0 where the PBKDF2 and MD5 password hashers raised UnicodeDecodeError for bytes passwords that were not valid UTF-8. Passwords supplied as str or as UTF-8 bytes are unaffected (#37184).
View originalPermalink
How 6.0.7 went

5.2.15

Security 5
  • Fixed signed cookie salt namespace collision in get_signed_cookie() by using unambiguous salt derivation; older Django versions' cookies accepted until Django 7.0 for backwards compatibility
  • Fixed potential unencrypted email transmission via STARTTLS in SMTP backend when EMAIL_USE_TLS is configured and STARTTLS handshake fails
  • Fixed UpdateCacheMiddleware and cache_page() incorrectly caching responses with private Cache-Control directives when using mixed or uppercase values
  • Fixed UpdateCacheMiddleware and cache_page() allowing responses to requests with Authorization header to be cached without varying on Authorization
  • Fixed UpdateCacheMiddleware incorrectly caching responses with leading or trailing whitespace in Vary header values

Django 5.2.15 release notes

June 3, 2026 Django 5.2.15 fixes five security issues with severity “low” in 5.2.14.

CVE-2026-6873: Signed cookie salt namespace collision

get_signed_cookie() derived the signing salt by concatenating the cookie name (key) and salt arguments. When distinct name and salt pairs produced the same concatenation, cookies could be accepted in a context different from the one where they were signed. Cookies are now signed with an unambiguous salt derivation. For backwards compatibility, cookies signed by older Django versions are accepted until Django 7.0. Projects affected by the above ambiguity should set SIGNED_COOKIE_LEGACY_SALT_FALLBACK to False to reject older cookies immediately. This issue has severity “low” according to the Django security policy.

CVE-2026-7666: Potential unencrypted email transmission via STARTTLS in the SMTP backend

When using EMAIL_USE_TLS, a failed STARTTLS handshake could leave a partially-initialized connection that would subsequently be reused for sending email without encryption. This can occur with fail_silently=True, as used by send_mail() and BrokenLinkEmailsMiddleware, among others. Connections configured with EMAIL_USE_SSL are not affected. This issue has severity “low” according to the Django security policy.

CVE-2026-8404: Potential exposure of private data via case-sensitive Cache-Control directives

UpdateCacheMiddleware and cache_page() incorrectly cached responses marked with private Cache-Control directives when using mixed or uppercase values (e.g. Private). The cache_control() decorator and patch_cache_control() function were not affected, since they normalize directives to lowercase. This issue only affects responses where Cache-Control is set manually. This issue has severity “low” according to the Django security policy.

CVE-2026-35193: Potential exposure of private data via missing Vary: Authorization

UpdateCacheMiddleware and cache_page() decorator allowed responses to requests bearing an Authorization header (and without Cache-Control: public) to be cached. To conform with the existing mechanism for constructing cache keys, responses to these requests will now vary on Authorization. This issue has severity “low” according to the Django security policy.

CVE-2026-48587: Potential exposure of private data via whitespace padding in Vary header

UpdateCacheMiddleware incorrectly cached responses whose Vary header values contained leading or trailing whitespace. Because has_vary_header() failed to strip that, a Vary: * header value with surrounding whitespace was not recognized as containing the wildcard, causing it to be stored and potentially served from the cache when it should not have been. This issue has severity “low” according to the Django security policy.

View originalPermalink
How 5.2.15 went

6.0.6

Fixed 1
  • Fixed an alert message on an admin changelist with ModelAdmin.list_editable referring to the "Run" button by its previous name
Security 5
  • Fixed signed cookie salt namespace collision in get_signed_cookie() by using an unambiguous salt derivation, with legacy salt fallback support until Django 7.0
  • Fixed potential unencrypted email transmission when using EMAIL_USE_TLS with a failed STARTTLS handshake that could leave a partially-initialized connection
  • Fixed UpdateCacheMiddleware and cache_page() incorrectly caching responses marked with private Cache-Control directives when using mixed or uppercase values
  • Fixed UpdateCacheMiddleware and cache_page() allowing responses to requests bearing an Authorization header to be cached without varying on Authorization
  • Fixed UpdateCacheMiddleware incorrectly caching responses whose Vary header values contained leading or trailing whitespace

Django 6.0.6 release notes

June 3, 2026 Django 6.0.6 fixes five security issues with severity “low” and one bug in 6.0.5.

CVE-2026-6873: Signed cookie salt namespace collision

get_signed_cookie() derived the signing salt by concatenating the cookie name (key) and salt arguments. When distinct name and salt pairs produced the same concatenation, cookies could be accepted in a context different from the one where they were signed. Cookies are now signed with an unambiguous salt derivation. For backwards compatibility, cookies signed by older Django versions are accepted until Django 7.0. Projects affected by the above ambiguity should set SIGNED_COOKIE_LEGACY_SALT_FALLBACK to False to reject older cookies immediately. This issue has severity “low” according to the Django security policy.

CVE-2026-7666: Potential unencrypted email transmission via STARTTLS in the SMTP backend

When using EMAIL_USE_TLS, a failed STARTTLS handshake could leave a partially-initialized connection that would subsequently be reused for sending email without encryption. This can occur with fail_silently=True, as used by send_mail() and BrokenLinkEmailsMiddleware, among others. Connections configured with EMAIL_USE_SSL are not affected. This issue has severity “low” according to the Django security policy.

CVE-2026-8404: Potential exposure of private data via case-sensitive Cache-Control directives

UpdateCacheMiddleware and cache_page() incorrectly cached responses marked with private Cache-Control directives when using mixed or uppercase values (e.g. Private). The cache_control() decorator and patch_cache_control() function were not affected, since they normalize directives to lowercase. This issue only affects responses where Cache-Control is set manually. This issue has severity “low” according to the Django security policy.

CVE-2026-35193: Potential exposure of private data via missing Vary: Authorization

UpdateCacheMiddleware and cache_page() decorator allowed responses to requests bearing an Authorization header (and without Cache-Control: public) to be cached. To conform with the existing mechanism for constructing cache keys, responses to these requests will now vary on Authorization. This issue has severity “low” according to the Django security policy.

CVE-2026-48587: Potential exposure of private data via whitespace padding in Vary header

UpdateCacheMiddleware incorrectly cached responses whose Vary header values contained leading or trailing whitespace. Because has_vary_header() failed to strip that, a Vary: * header value with surrounding whitespace was not recognized as containing the wildcard, causing it to be stored and potentially served from the cache when it should not have been. This issue has severity “low” according to the Django security policy.

Bugfixes
  • Fixed a bug in Django 6.0 where an alert message on an admin changelist with ModelAdmin.list_editable referred to the “Run” button by its previous name (#37094).
View originalPermalink
How 6.0.6 went

5.2.14

Security 3
  • Fixed potential denial-of-service vulnerability in ASGI requests where missing or understated Content-Length header could bypass FILE_UPLOAD_MAX_MEMORY_SIZE limit
  • Fixed session fixation vulnerability where response headers did not vary on cookies if a session was not modified with SESSION_SAVE_EVERY_REQUEST set to True
  • Fixed UpdateCacheMiddleware incorrectly caching requests where the Vary header contained an asterisk, which could lead to private data being stored and served

Django 5.2.14 release notes

May 5, 2026 Django 5.2.14 fixes three security issues with severity “low” in 5.2.13.

CVE-2026-5766: Potential denial-of-service vulnerability in ASGI requests via file upload limit bypass

ASGI requests with a missing or understated Content-Length header could bypass the FILE_UPLOAD_MAX_MEMORY_SIZE limit, potentially loading large files into memory and causing service degradation. As a reminder, Django expects a limit to be configured at the web server level rather than solely relying on FILE_UPLOAD_MAX_MEMORY_SIZE. This issue has severity “low” according to the Django security policy.

CVE-2026-35192: Session fixation via public cached pages and SESSION_SAVE_EVERY_REQUEST

Response headers did not vary on cookies if a session was not modified, but SESSION_SAVE_EVERY_REQUEST was True. A remote attacker could steal a user’s session after that user visits a cached public page. This issue has severity “low” according to the Django security policy.

CVE-2026-6907: Potential exposure of private data due to incorrect handling of Vary: * in UpdateCacheMiddleware

Previously, UpdateCacheMiddleware would erroneously cache requests where the Vary header contained an asterisk ('*'). This could lead to private data being stored and served. This issue has severity “low” according to the Django security policy.

View originalPermalink
How 5.2.14 went

6.0.5

Fixed 2
  • Fixed a misplaced </div> in the django/contrib/admin/templates/admin/change_list.html template that could be problematic when overriding the pagination block
  • Fixed a bug where deprecation warnings incorrectly skipped lines from third-party packages prefixed with "django"
Security 3
  • Fixed potential denial-of-service vulnerability in ASGI requests where a missing or understated Content-Length header could bypass the FILE_UPLOAD_MAX_MEMORY_SIZE limit
  • Fixed session fixation vulnerability where response headers did not vary on cookies if a session was not modified but SESSION_SAVE_EVERY_REQUEST was True
  • Fixed potential exposure of private data due to incorrect handling of Vary: * in UpdateCacheMiddleware that would erroneously cache requests

Django 6.0.5 release notes

May 5, 2026 Django 6.0.5 fixes three security issues with severity “low” and several bugs in 6.0.4.

CVE-2026-5766: Potential denial-of-service vulnerability in ASGI requests via file upload limit bypass

ASGI requests with a missing or understated Content-Length header could bypass the FILE_UPLOAD_MAX_MEMORY_SIZE limit, potentially loading large files into memory and causing service degradation. As a reminder, Django expects a limit to be configured at the web server level rather than solely relying on FILE_UPLOAD_MAX_MEMORY_SIZE. This issue has severity “low” according to the Django security policy.

CVE-2026-35192: Session fixation via public cached pages and SESSION_SAVE_EVERY_REQUEST

Response headers did not vary on cookies if a session was not modified, but SESSION_SAVE_EVERY_REQUEST was True. A remote attacker could steal a user’s session after that user visits a cached public page. This issue has severity “low” according to the Django security policy.

CVE-2026-6907: Potential exposure of private data due to incorrect handling of Vary: * in UpdateCacheMiddleware

Previously, UpdateCacheMiddleware would erroneously cache requests where the Vary header contained an asterisk ('*'). This could lead to private data being stored and served. This issue has severity “low” according to the Django security policy.

Bugfixes
  • Fixed a misplaced in the django/contrib/admin/templates/admin/change_list.html template added in Django 6.0 that could be problematic when overriding the pagination block (#37029).
  • Fixed a bug in Django 6.0 where deprecation warnings incorrectly skipped lines from third-party packages prefixed with “django” (#37067).
View originalPermalink
How 6.0.5 went

4.2.30

Security 5
  • Fixed ASGI header spoofing vulnerability (CVE-2026-3902) by ignoring headers containing underscores in ASGIRequest
  • Fixed privilege abuse in GenericInlineModelAdmin (CVE-2026-4277) by validating add permissions on inline model instances for forged POST data
  • Fixed privilege abuse in ModelAdmin.list_editable (CVE-2026-4292) by preventing new instances from being created via forged POST data
  • Fixed potential denial-of-service vulnerability in MultiPartParser (CVE-2026-33033) when handling base64-encoded file uploads with excessive whitespace
  • Fixed potential denial-of-service vulnerability in ASGI requests (CVE-2026-33034) by enforcing DATA_UPLOAD_MAX_MEMORY_SIZE limit even with missing or understated Content-Length headers

Django 4.2.30 release notes

April 7, 2026 Django 4.2.30 fixes one security issue with severity “moderate” and four security issues with severity “low” in 4.2.29.

CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation

ASGIRequest normalizes header names following WSGI conventions, mapping hyphens to underscores. As a result, even in configurations where reverse proxies carefully strip security-sensitive headers named with hyphens, such a header could be spoofed by supplying a header named with underscores. Under WSGI, it is the responsibility of the server or proxy to avoid ambiguous mappings. (Django’s runserver was patched in CVE 2015-0219.) But under ASGI, there is not the same uniform expectation, even if many proxies protect against this under default configuration (including nginx via underscores_in_headers off;). Headers containing underscores are now ignored by ASGIRequest, matching the behavior of Daphne, the reference server for ASGI. This issue has severity “low” according to the Django security policy.

CVE-2026-4277: Privilege abuse in GenericInlineModelAdmin

Add permissions on inline model instances were not validated on submission of forged POST data in GenericInlineModelAdmin. This issue has severity “low” according to the Django security policy.

CVE-2026-4292: Privilege abuse in ModelAdmin.list_editable

Admin changelist forms using list_editable incorrectly allowed new instances to be created via forged POST data. This issue has severity “low” according to the Django security policy.

CVE-2026-33033: Potential denial-of-service vulnerability in MultiPartParser via base64-encoded file upload

When using django.http.multipartparser.MultiPartParser, multipart uploads with Content-Transfer-Encoding: base64 that include excessive whitespace may trigger repeated memory copying, potentially degrading performance. This issue has severity “moderate” according to the Django security policy.

CVE-2026-33034: Potential denial-of-service vulnerability in ASGI requests via memory upload limit bypass

ASGI requests with a missing or understated Content-Length header could bypass the DATA_UPLOAD_MAX_MEMORY_SIZE limit when reading HttpRequest.body, potentially loading an unbounded request body into memory and causing service degradation. This issue has severity “low” according to the Django security policy.

View originalPermalink
How 4.2.30 went

5.2.13

Security 5
  • Fixed ASGI header spoofing vulnerability via underscore/hyphen conflation by ignoring headers containing underscores in ASGIRequest
  • Fixed privilege abuse in GenericInlineModelAdmin where add permissions on inline model instances were not validated on POST submission
  • Fixed privilege abuse in ModelAdmin.list_editable where new instances could be created via forged POST data
  • Fixed potential denial-of-service vulnerability in MultiPartParser where base64-encoded file uploads with excessive whitespace could trigger repeated memory copying
  • Fixed potential denial-of-service vulnerability in ASGI requests where missing or understated Content-Length headers could bypass DATA_UPLOAD_MAX_MEMORY_SIZE limit

Django 5.2.13 release notes

April 7, 2026 Django 5.2.13 fixes one security issue with severity “moderate” and four security issues with severity “low” in 5.2.12.

CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation

ASGIRequest normalizes header names following WSGI conventions, mapping hyphens to underscores. As a result, even in configurations where reverse proxies carefully strip security-sensitive headers named with hyphens, such a header could be spoofed by supplying a header named with underscores. Under WSGI, it is the responsibility of the server or proxy to avoid ambiguous mappings. (Django’s runserver was patched in CVE 2015-0219.) But under ASGI, there is not the same uniform expectation, even if many proxies protect against this under default configuration (including nginx via underscores_in_headers off;). Headers containing underscores are now ignored by ASGIRequest, matching the behavior of Daphne, the reference server for ASGI. This issue has severity “low” according to the Django security policy.

CVE-2026-4277: Privilege abuse in GenericInlineModelAdmin

Add permissions on inline model instances were not validated on submission of forged POST data in GenericInlineModelAdmin. This issue has severity “low” according to the Django security policy.

CVE-2026-4292: Privilege abuse in ModelAdmin.list_editable

Admin changelist forms using list_editable incorrectly allowed new instances to be created via forged POST data. This issue has severity “low” according to the Django security policy.

CVE-2026-33033: Potential denial-of-service vulnerability in MultiPartParser via base64-encoded file upload

When using django.http.multipartparser.MultiPartParser, multipart uploads with Content-Transfer-Encoding: base64 that include excessive whitespace may trigger repeated memory copying, potentially degrading performance. This issue has severity “moderate” according to the Django security policy.

CVE-2026-33034: Potential denial-of-service vulnerability in ASGI requests via memory upload limit bypass

ASGI requests with a missing or understated Content-Length header could bypass the DATA_UPLOAD_MAX_MEMORY_SIZE limit when reading HttpRequest.body, potentially loading an unbounded request body into memory and causing service degradation. This issue has severity “low” according to the Django security policy.

View originalPermalink
How 5.2.13 went

6.0.4

Fixed 3
  • Fixed a regression where alogin() and alogout() did not respectively set or clear request.user if it had already been materialized by sync middleware
  • Fixed a regression in admin forms where RelatedFieldWidgetWrapper incorrectly wrapped all widgets in a fieldset
  • Fixed a bug where the fields.E348 system check did not detect name clashes between model managers and related_names for non-self-referential relationships
Security 5
  • Headers containing underscores are now ignored by ASGIRequest to prevent header spoofing via underscore/hyphen conflation (CVE-2026-3902)
  • Add permissions on inline model instances are now validated on submission of forged POST data in GenericInlineModelAdmin (CVE-2026-4277)
  • Admin changelist forms using list_editable no longer allow new instances to be created via forged POST data (CVE-2026-4292)
  • Fixed potential denial-of-service vulnerability in MultiPartParser when processing base64-encoded file uploads with excessive whitespace (CVE-2026-33033)
  • Fixed potential denial-of-service vulnerability in ASGI requests where missing or understated Content-Length header could bypass DATA_UPLOAD_MAX_MEMORY_SIZE limit (CVE-2026-33034)

Django 6.0.4 release notes

April 7, 2026 Django 6.0.4 fixes one security issue with severity “moderate”, four security issues with severity “low”, and several bugs in 6.0.3.

CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation

ASGIRequest normalizes header names following WSGI conventions, mapping hyphens to underscores. As a result, even in configurations where reverse proxies carefully strip security-sensitive headers named with hyphens, such a header could be spoofed by supplying a header named with underscores. Under WSGI, it is the responsibility of the server or proxy to avoid ambiguous mappings. (Django’s runserver was patched in CVE 2015-0219.) But under ASGI, there is not the same uniform expectation, even if many proxies protect against this under default configuration (including nginx via underscores_in_headers off;). Headers containing underscores are now ignored by ASGIRequest, matching the behavior of Daphne, the reference server for ASGI. This issue has severity “low” according to the Django security policy.

CVE-2026-4277: Privilege abuse in GenericInlineModelAdmin

Add permissions on inline model instances were not validated on submission of forged POST data in GenericInlineModelAdmin. This issue has severity “low” according to the Django security policy.

CVE-2026-4292: Privilege abuse in ModelAdmin.list_editable

Admin changelist forms using list_editable incorrectly allowed new instances to be created via forged POST data. This issue has severity “low” according to the Django security policy.

CVE-2026-33033: Potential denial-of-service vulnerability in MultiPartParser via base64-encoded file upload

When using django.http.multipartparser.MultiPartParser, multipart uploads with Content-Transfer-Encoding: base64 that include excessive whitespace may trigger repeated memory copying, potentially degrading performance. This issue has severity “moderate” according to the Django security policy.

CVE-2026-33034: Potential denial-of-service vulnerability in ASGI requests via memory upload limit bypass

ASGI requests with a missing or understated Content-Length header could bypass the DATA_UPLOAD_MAX_MEMORY_SIZE limit when reading HttpRequest.body, potentially loading an unbounded request body into memory and causing service degradation. This issue has severity “low” according to the Django security policy.

Bugfixes
  • Fixed a regression in Django 6.0 where alogin() and alogout() did not respectively set or clear request.user if it had already been materialized (e.g., by sync middleware) (#37017).
  • Fixed a regression in Django 6.0 in admin forms where RelatedFieldWidgetWrapper incorrectly wrapped all widgets in a (#36949).
  • Fixed a bug in Django 6.0 where the fields.E348 system check did not detect name clashes between model managers and related_names for non-self-referential relationships (#36973).
View originalPermalink
How 6.0.4 went

4.2.29

Security 2
  • Fixed potential denial-of-service vulnerability in URLField via Unicode normalization on Windows by simplifying scheme detection in URLField.to_python() to avoid Unicode normalization
  • Fixed potential incorrect permissions on newly created file system objects in file-system storage and file-based cache backends by applying requested permissions via chmod() after mkdir() instead of relying on process umask

Django 4.2.29 release notes

March 3, 2026 Django 4.2.29 fixes a security issue with severity “moderate” and a security issue with severity “low” in 4.2.28.

CVE-2026-25673: Potential denial-of-service vulnerability in URLField via Unicode normalization on Windows

The URLField form field’s to_python() method used urlsplit() to determine whether to prepend a URL scheme to the submitted value. On Windows, urlsplit() performs NFKC normalization, which can be disproportionately slow for large inputs containing certain characters. URLField.to_python() now uses a simplified scheme detection, avoiding Unicode normalization entirely and deferring URL validation to the appropriate layers. As a result, while leading and trailing whitespace is still stripped by default, characters such as newlines, tabs, and other control characters within the value are no longer handled by URLField.to_python(). When using the default URLValidator, these values will continue to raise ValidationError during validation, but if you rely on custom validators, ensure they do not depend on the previous behavior of URLField.to_python(). This issue has severity “moderate” according to the Django security policy.

CVE-2026-25674: Potential incorrect permissions on newly created file system objects

Django’s file-system storage and file-based cache backends used the process umask to control permissions when creating directories. In multi-threaded environments, one thread’s temporary umask change can affect other threads’ file and directory creation, resulting in file system objects being created with unintended permissions. Django now applies the requested permissions via chmod() after mkdir(), removing the dependency on the process-wide umask. This issue has severity “low” according to the Django security policy.

View originalPermalink
How 4.2.29 went

5.2.12

Fixed 1
  • Fixed NameError when inspecting functions making use of deferred annotations in Python 3.14
Security 2
  • Fixed potential denial-of-service vulnerability in URLField via Unicode normalization on Windows by using simplified scheme detection in URLField.to_python() to avoid Unicode normalization entirely
  • Fixed potential incorrect permissions on newly created file system objects in file-system storage and file-based cache backends by applying requested permissions via chmod() after mkdir() instead of relying on process-wide umask

Django 5.2.12 release notes

March 3, 2026 Django 5.2.12 fixes a security issue with severity “moderate” and a security issue with severity “low” in 5.2.11. It also fixes one bug related to support for Python 3.14.

CVE-2026-25673: Potential denial-of-service vulnerability in URLField via Unicode normalization on Windows

The URLField form field’s to_python() method used urlsplit() to determine whether to prepend a URL scheme to the submitted value. On Windows, urlsplit() performs NFKC normalization, which can be disproportionately slow for large inputs containing certain characters. URLField.to_python() now uses a simplified scheme detection, avoiding Unicode normalization entirely and deferring URL validation to the appropriate layers. As a result, while leading and trailing whitespace is still stripped by default, characters such as newlines, tabs, and other control characters within the value are no longer handled by URLField.to_python(). When using the default URLValidator, these values will continue to raise ValidationError during validation, but if you rely on custom validators, ensure they do not depend on the previous behavior of URLField.to_python(). This issue has severity “moderate” according to the Django security policy.

CVE-2026-25674: Potential incorrect permissions on newly created file system objects

Django’s file-system storage and file-based cache backends used the process umask to control permissions when creating directories. In multi-threaded environments, one thread’s temporary umask change can affect other threads’ file and directory creation, resulting in file system objects being created with unintended permissions. Django now applies the requested permissions via chmod() after mkdir(), removing the dependency on the process-wide umask. This issue has severity “low” according to the Django security policy.

Bugfixes
  • Fixed NameError when inspecting functions making use of deferred annotations in Python 3.14 (#36903).
View originalPermalink
How 5.2.12 went

6.0.3

Fixed 5
  • Fixed NameError when inspecting functions making use of deferred annotations in Python 3.14
  • Fixed AttributeError when subclassing builtin lookups and neglecting to override as_sql() to accept any sequence
  • Fixed TypeError when deprecation warnings are emitted in environments importing Django by namespace
  • Fixed visual regression where fieldset legends were misaligned in the admin
  • Prevented the django.tasks.signals.task_finished signal from writing extraneous log messages when no exceptions are encountered
Security 2
  • Fixed potential denial-of-service vulnerability in URLField via Unicode normalization on Windows by using simplified scheme detection instead of urlsplit()
  • Fixed potential incorrect permissions on newly created file system objects in file-system storage and file-based cache backends by applying requested permissions via chmod() after mkdir()

Django 6.0.3 release notes

March 3, 2026 Django 6.0.3 fixes a security issue with severity “moderate”, a security issue with severity “low”, and several bugs in 6.0.2.

CVE-2026-25673: Potential denial-of-service vulnerability in URLField via Unicode normalization on Windows

The URLField form field’s to_python() method used urlsplit() to determine whether to prepend a URL scheme to the submitted value. On Windows, urlsplit() performs NFKC normalization, which can be disproportionately slow for large inputs containing certain characters. URLField.to_python() now uses a simplified scheme detection, avoiding Unicode normalization entirely and deferring URL validation to the appropriate layers. As a result, while leading and trailing whitespace is still stripped by default, characters such as newlines, tabs, and other control characters within the value are no longer handled by URLField.to_python(). When using the default URLValidator, these values will continue to raise ValidationError during validation, but if you rely on custom validators, ensure they do not depend on the previous behavior of URLField.to_python(). This issue has severity “moderate” according to the Django security policy.

CVE-2026-25674: Potential incorrect permissions on newly created file system objects

Django’s file-system storage and file-based cache backends used the process umask to control permissions when creating directories. In multi-threaded environments, one thread’s temporary umask change can affect other threads’ file and directory creation, resulting in file system objects being created with unintended permissions. Django now applies the requested permissions via chmod() after mkdir(), removing the dependency on the process-wide umask. This issue has severity “low” according to the Django security policy.

Bugfixes
  • Fixed NameError when inspecting functions making use of deferred annotations in Python 3.14 (#36903).
  • Fixed AttributeError when subclassing builtin lookups and neglecting to override as_sql() to accept any sequence (#36934).
  • Fixed TypeError when deprecation warnings are emitted in environments importing Django by namespace (#36961).
  • Fixed a visual regression where fieldset legends were misaligned in the admin (#36920).
  • Prevented the django.tasks.signals.task_finished signal from writing extraneous log messages when no exceptions are encountered (#36951).
View originalPermalink
How 6.0.3 went
View all

Discussion