Why CSRF token cookies don't need to be httpOnly
CSRF token cookies are typically sent without httpOnly set to true. But is that a secure practice?
Published: 20 Jul, 2024
Security tools will often freak out when they see that your CSRF token is being stored in a cookie without the httpOnly flag set.
But if you set httpOnly, client side libraries like fetch won’t have access to the cookie. To make non-GET requests against your back-end, you must send the CSRF token with every such request. This is typically done by injecting a custom header into the request called something like X-CSRFTOKEN when making the request.
Since front-end frameworks like React run entirely on the client, there’s no way to get access to httpOnly cookies. If you use httpOnly for your CSRF token, you won’t be able to perform requests like POST, PATCH, DELETE, etc.
That’s why your CSRF token needs to be in a cookie with httpOnly set to false.
But isn’t this a security problem?
If you don’t set httpOnly, an attacker who injected a piece of Javascript on your page by manipulating the user or his browser will be able to gain access to your CSRF token, and subsequently, perform requests as if they were made by the user himself.
Fortunately, there’s a good measure we can take against such attacks.
Use Content Security Policy (CSP)
CSP was originally designed to handle another class of security exploits known as XSS. It works amazingly for our attack scenario here because while we’re no longer vulnerable to direct CSRF attacks, attackers can steal the token via means of XSS attacks and use it directly.
CSP allows you to specify which origins you trust for your website’s assets. If your website is hosted at mywebsite.dev, you can set it to only allow scripts to be loaded from this specific domain, and not something like anotherwebsite.io.
With this mitigation in place, even if an attacker is able to inject a script tag on your web page, the user’s browser will refuse to load it because it’s not hosted on your domain. Since the script won’t load, the attacker can’t get access to the CSRF token cookie.
All you have to do is set the Content-Security-Policy header to something like default-src ‘self’ on requests originating from the server that your front-end application is hosted at. See more examples here.
As you can see, there’s no reason to freak out about CSRF token cookies not being httpOnly because modern browsers provide us with adequate protection against XSS attacks.