{"title":"Django 1.9.3 release notes","version":"dev","locale":"en","docname":"releases/1.9.3","url":"/en/dev/releases/1.9.3/","canonical":"https://djangodocs.dev/en/dev/releases/1.9.3/","summary":"Django 1.9.3 fixes two security issues and several bugs in 1.9.2. Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and…","html":"<h1>Django 1.9.3 release notes<a class=\"heading-anchor\" href=\"#django-1-9-3-release-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p><em>March 1, 2016</em></p>\n<p>Django 1.9.3 fixes two security issues and several bugs in 1.9.2.</p>\n<section id=\"cve-2016-2512-malicious-redirect-and-possible-xss-attack-via-user-supplied-redirect-urls-containing-basic-auth\">\n<h2>CVE-2016-2512: Malicious redirect and possible XSS attack via user-supplied redirect URLs containing basic auth<a class=\"heading-anchor\" href=\"#cve-2016-2512-malicious-redirect-and-possible-xss-attack-via-user-supplied-redirect-urls-containing-basic-auth\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django relies on user input in some cases (e.g.\n<code class=\"docutils literal notranslate\">django.contrib.auth.views.login()</code> and <a class=\"reference internal\" href=\"/en/dev/topics/i18n/\"><span class=\"doc\">i18n</span></a>)\nto redirect the user to an “on success” URL. The security check for these\nredirects (namely <code class=\"docutils literal notranslate\">django.utils.http.is_safe_url()</code>) considered some URLs\nwith basic authentication credentials “safe” when they shouldn’t be.</p>\n<p>For example, a URL like <code class=\"docutils literal notranslate\">http://mysite.example.com\\&#64;attacker.com</code> would be\nconsidered safe if the request’s host is <code class=\"docutils literal notranslate\">http://mysite.example.com</code>, but\nredirecting to this URL sends the user to <code class=\"docutils literal notranslate\">attacker.com</code>.</p>\n<p>Also, if a developer relies on <code class=\"docutils literal notranslate\">is_safe_url()</code> to provide safe redirect\ntargets and puts such a URL into a link, they could suffer from an XSS attack.</p>\n</section>\n<section id=\"cve-2016-2513-user-enumeration-through-timing-difference-on-password-hasher-work-factor-upgrade\">\n<h2>CVE-2016-2513: User enumeration through timing difference on password hasher work factor upgrade<a class=\"heading-anchor\" href=\"#cve-2016-2513-user-enumeration-through-timing-difference-on-password-hasher-work-factor-upgrade\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>In each major version of Django since 1.6, the default number of iterations for\nthe <code class=\"docutils literal notranslate\">PBKDF2PasswordHasher</code> and its subclasses has increased. This improves\nthe security of the password as the speed of hardware increases, however, it\nalso creates a timing difference between a login request for a user with a\npassword encoded in an older number of iterations and login request for a\nnonexistent user (which runs the default hasher’s default number of iterations\nsince Django 1.6).</p>\n<p>This only affects users who haven’t logged in since the iterations were\nincreased. The first time a user logs in after an iterations increase, their\npassword is updated with the new iterations and there is no longer a timing\ndifference.</p>\n<p>The new <code class=\"docutils literal notranslate\">BasePasswordHasher.harden_runtime()</code> method allows hashers to bridge\nthe runtime gap between the work factor (e.g. iterations) supplied in existing\nencoded passwords and the default work factor of the hasher. This method\nis implemented for <code class=\"docutils literal notranslate\">PBKDF2PasswordHasher</code>  and <code class=\"docutils literal notranslate\">BCryptPasswordHasher</code>.\nThe number of rounds for the latter hasher hasn’t changed since Django 1.4, but\nsome projects may subclass it and increase the work factor as needed.</p>\n<p>A warning will be emitted for any <a class=\"reference internal\" href=\"/en/dev/topics/auth/passwords/#write-your-own-password-hasher\"><span class=\"std std-ref\">third-party password hashers that don’t\nimplement</span></a> a <code class=\"docutils literal notranslate\">harden_runtime()</code> method.</p>\n<p>If you have different password hashes in your database (such as SHA1 hashes\nfrom users who haven’t logged in since the default hasher switched to PBKDF2\nin Django 1.4), the timing difference on a login request for these users may be\neven greater and this fix doesn’t remedy that difference (or any difference\nwhen changing hashers). You may be able to <a class=\"reference internal\" href=\"/en/dev/topics/auth/passwords/#wrapping-password-hashers\"><span class=\"std std-ref\">upgrade those hashes</span></a> to prevent a timing attack for that case.</p>\n</section>\n<section id=\"bugfixes\">\n<h2>Bugfixes<a class=\"heading-anchor\" href=\"#bugfixes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<ul class=\"simple\">\n<li><p>Skipped URL checks (new in 1.9) if the <code class=\"docutils literal notranslate\">ROOT_URLCONF</code> setting isn’t defined\n(<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26155\">#26155</a>).</p></li>\n<li><p>Fixed a crash on PostgreSQL that prevented using <code class=\"docutils literal notranslate\">TIME_ZONE=None</code> and\n<code class=\"docutils literal notranslate\">USE_TZ=False</code> (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26177\">#26177</a>).</p></li>\n<li><p>Added system checks for query name clashes of hidden relationships\n(<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26162\">#26162</a>).</p></li>\n<li><p>Fixed a regression for cases where\n<code class=\"docutils literal notranslate\">ForeignObject.get_extra_descriptor_filter()</code> returned a <code class=\"docutils literal notranslate\">Q</code> object\n(<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26153\">#26153</a>).</p></li>\n<li><p>Fixed regression with an <code class=\"docutils literal notranslate\">__in=qs</code> lookup for a <code class=\"docutils literal notranslate\">ForeignKey</code> with\n<code class=\"docutils literal notranslate\">to_field</code> set (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26196\">#26196</a>).</p></li>\n<li><p>Made <code class=\"docutils literal notranslate\">forms.FileField</code> and <code class=\"docutils literal notranslate\">utils.translation.lazy_number()</code> picklable\n(<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26212\">#26212</a>).</p></li>\n<li><p>Fixed <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/fields/#django.contrib.postgres.fields.RangeField\" title=\"django.contrib.postgres.fields.RangeField\"><code class=\"xref py py-class docutils literal notranslate\">RangeField</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/fields/#django.contrib.postgres.fields.ArrayField\" title=\"django.contrib.postgres.fields.ArrayField\"><code class=\"xref py py-class docutils literal notranslate\">ArrayField</code></a> serialization with\n<code class=\"docutils literal notranslate\">None</code> values (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26215\">#26215</a>).</p></li>\n<li><p>Fixed a crash when filtering by a <code class=\"docutils literal notranslate\">Decimal</code> in <code class=\"docutils literal notranslate\">RawQuery</code>\n(<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26219\">#26219</a>).</p></li>\n<li><p>Reallowed dashes in top-level domain names of URLs checked by\n<code class=\"docutils literal notranslate\">URLValidator</code> to fix a regression in Django 1.8 (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26204\">#26204</a>).</p></li>\n<li><p>Fixed some crashing deprecation shims in <code class=\"docutils literal notranslate\">SimpleTemplateResponse</code> that\nregressed in Django 1.9 (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26253\">#26253</a>).</p></li>\n<li><p>Fixed <code class=\"docutils literal notranslate\">BoundField</code> to reallow slices of subwidgets (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26267\">#26267</a>).</p></li>\n<li><p>Changed the admin’s “permission denied” message in the login template to use\n<code class=\"docutils literal notranslate\">get_username</code> instead of <code class=\"docutils literal notranslate\">username</code> to support custom user models\n(<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26231\">#26231</a>).</p></li>\n<li><p>Fixed a crash when passing a nonexistent template name to the cached template\nloader’s <code class=\"docutils literal notranslate\">load_template()</code> method (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26280\">#26280</a>).</p></li>\n<li><p>Prevented <code class=\"docutils literal notranslate\">ContentTypeManager</code> instances from sharing their cache\n(<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26286\">#26286</a>).</p></li>\n<li><p>Reverted a change in Django 1.9.2 (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/25858\">#25858</a>) that prevented relative\nlazy relationships defined on abstract models to be resolved according to\ntheir concrete model’s <code class=\"docutils literal notranslate\">app_label</code> (<a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/26186\">#26186</a>).</p></li>\n</ul>\n</section>","rootId":"django-1-9-3-release-notes","toc":[{"title":"CVE-2016-2512: Malicious redirect and possible XSS attack via user-supplied redirect URLs containing basic auth","anchor":"cve-2016-2512-malicious-redirect-and-possible-xss-attack-via-user-supplied-redirect-urls-containing-basic-auth","children":[]},{"title":"CVE-2016-2513: User enumeration through timing difference on password hasher work factor upgrade","anchor":"cve-2016-2513-user-enumeration-through-timing-difference-on-password-hasher-work-factor-upgrade","children":[]},{"title":"Bugfixes","anchor":"bugfixes","children":[]}],"breadcrumbs":[{"docname":"releases/index","title":"Release notes","url":"/en/dev/releases/"}],"prev":{"docname":"releases/1.9.4","title":"Django 1.9.4 release notes","url":"/en/dev/releases/1.9.4/"},"next":{"docname":"releases/1.9.2","title":"Django 1.9.2 release notes","url":"/en/dev/releases/1.9.2/"},"formats":{"html":"/en/dev/releases/1.9.3/","markdown":"/en/dev/releases/1.9.3.md","json":"/en/dev/releases/1.9.3.json"},"source":"https://github.com/django/django/blob/main/docs/releases/1.9.3.txt","official":"https://docs.djangoproject.com/en/dev/releases/1.9.3/","inVersions":["dev","6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en"]}