April 21, 2014
Django 1.6.3 fixes several bugs in 1.6.2, including three security issues, and makes one backwards-incompatible change:
reverse()
¶Django’s URL handling is based on a mapping of regex patterns (representing the URLs) to callable views, and Django’s own processing consists of matching a requested URL against those patterns to determine the appropriate view to invoke.
Django also provides a convenience function – reverse()
– which performs
this process in the opposite direction. The reverse()
function takes
information about a view and returns a URL which would invoke that view. Use
of reverse()
is encouraged for application developers, as the output of
reverse()
is always based on the current URL patterns, meaning developers
do not need to change other code when making changes to URLs.
One argument signature for reverse()
is to pass a dotted Python
path to the desired view. In this situation, Django will import the
module indicated by that dotted path as part of generating the
resulting URL. If such a module has import-time side effects, those
side effects will occur.
Thus it is possible for an attacker to cause unexpected code execution, given the following conditions:
To remedy this, reverse()
will now only accept and import dotted
paths based on the view-containing modules listed in the project’s URL
pattern configuration, so as to ensure that only modules
the developer intended to be imported in this fashion can or will be imported.
Django includes both a caching framework and a system for preventing cross-site request forgery (CSRF) attacks. The CSRF-protection system is based on a random nonce sent to the client in a cookie which must be sent by the client on future requests and, in forms, a hidden value which must be submitted back with the form.
The caching framework includes an option to cache responses to anonymous (i.e., unauthenticated) clients.
When the first anonymous request to a given page is by a client which did not have a CSRF cookie, the cache framework will also cache the CSRF cookie and serve the same nonce to other anonymous clients who do not have a CSRF cookie. This can allow an attacker to obtain a valid CSRF cookie value and perform attacks which bypass the check for the cookie.
To remedy this, the caching framework will no longer cache such responses. The heuristic for this will be:
Vary: Cookie
header is set on the response, then the
response will not be cached.The MySQL database is known to “typecast” on certain queries; for example, when querying a table which contains string values, but using a query which filters based on an integer value, MySQL will first silently coerce the strings to integers and return a result based on that.
If a query is performed without first converting values to the appropriate type, this can produce unexpected results, similar to what would occur if the query itself had been manipulated.
Django’s model field classes are aware of their own types and most such classes perform explicit conversion of query arguments to the correct database-level type before querying. However, three model field classes did not correctly convert their arguments:
FilePathField
GenericIPAddressField
IPAddressField
These three fields have been updated to convert their arguments to the correct types before querying.
Additionally, developers of custom model fields are now warned via
documentation to ensure their custom field classes will perform
appropriate type conversions, and users of the raw()
and extra()
query methods – which allow the
developer to supply raw SQL or SQL fragments – will be advised to ensure they
perform appropriate manual type conversions prior to executing queries.
select_for_update()
requires a transaction¶Historically, queries that use
select_for_update()
could be
executed in autocommit mode, outside of a transaction. Before Django
1.6, Django’s automatic transactions mode allowed this to be used to
lock records until the next write operation. Django 1.6 introduced
database-level autocommit; since then, execution in such a context
voids the effect of select_for_update()
. It is, therefore, assumed
now to be an error and raises an exception.
This change was made because such errors can be caused by including an
app which expects global transactions (e.g. ATOMIC_REQUESTS
set to True
), or Django’s old autocommit
behavior, in a project which runs without them; and further, such
errors may manifest as data-corruption bugs.
This change may cause test failures if you use select_for_update()
in a test class which is a subclass of
TransactionTestCase
rather than
TestCase
.
iso-8859-1
encoding
(#21996).AttributeError
when using
bulk_create()
with ForeignObject
(#21566).QuerySet
s that use F() + timedelta()
when their query
was compiled more once
(#21643).widget
class attribute of
IntegerField
subclasses from being overwritten by the
code in their __init__
method
(#22245).strip_tags()
accuracy (but it still cannot
guarantee an HTML-safe result, as stated in the documentation).django.contrib.gis
SQL compiler for
non-concrete fields (#22250).ModelAdmin.preserve_filters
when running a site with
a URL prefix (#21795).find_command
management utility when the PATH
environment variable wasn’t set
(#22256).changepassword
on Windows
(#22364)._set_autocommit
(#22321).prefetch_related
that caused the related objects
query to include an unnecessary join
(#21760).Additionally, Django’s vendored version of six, django.utils.six
has been
upgraded to the latest release (1.6.1).
Jul 27, 2022