Django won't set HttpOnly for csrftoken cookie Django won't set HttpOnly for csrftoken cookie nginx nginx

Django won't set HttpOnly for csrftoken cookie


You have only configured it to have the CSRF token be set to Secure (i.e. only sent over https requests) and not to be HttpOnly (i.e. not available to Javascript).

Looking at the Django documentation you also need to set CSRF_COOKIE_HTTPONLY. However the documentation rightly points out:

Designating the CSRF cookie as HttpOnly doesn’t offer any practical protection because CSRF is only to protect against cross-domain attacks. If an attacker can read the cookie via JavaScript, they’re already on the same domain as far as the browser knows, so they can do anything they like anyway. (XSS is a much bigger hole than CSRF.)

Although the setting offers little practical benefit, it’s sometimes required by security auditors.

It also depends how you have implemented CSRF. There are basically two methods for forms:

  1. Set a hidden CSRF field for each form and make this field generate a unique value each time the form is loaded. Therefore if the form submission includes a valid code, then you know the request came from your domain. This is complicated on the server side, as it requires keeping track of valid tokens and also means each form must be dynamically generated to include a random token, but is easier on client side as uses standard form requests rather than JavaScript. For this protection the CSRF cookie is not needed and is not used even if it is present.

  2. The other method invokes setting a CSRF cookie, and having the Javascript read this and send it in a HTTP header (usually X-CSRF-TOKEN). A CSRF request from another domain won't have access to this CSRF cookie so won't be able to set the header correctly. As the cookies will be also be sent on all requests it's easy for the server to check the cookie in the HTTP Request matches the header set in the request. Which means the request came from a somewhere that has access to the cookies, which means it came from same domain. Which means it's not a CSRF attack. This is easier to implement on the server side (as no need to keep a list of active Tokens) but requires Javascript at the front end and requires a CSRF token not to be HttpOnly - precisely because the Token is supposed to be read by Client side Javascript!

Again the Django documentation warns against this:

If you enable this and need to send the value of the CSRF token with an AJAX request, your JavaScript must pull the value from a hidden CSRF token form input on the page instead of from the cookie.

So, all in all, it is not recommended to set the HttpOnly attribute for this cookie. It limits you, adds no real protection, and makes the cookie itself meaningless.

You will get it highlighted in and Pen Test reports on your site (including https://detectify.com by the looks of things) but should accept that as you are comfortable that this is correct. Not sure if it's possible to whitelist this cookie in https://detectify.com so it doesn't alert each time?