https://smagin.fyi/posts/cross-site-requests/ SMAGIN about within means Cross-Site Requests Why do we have both CSRF protection and CORS? March 1, 2025 Hello, Internet. I thought about cross-site requests and realised we have both CSRF protection and CORS and it doesn't make sense from the first glance. It does generally, but I need a thousand words to make it so. CSRF stands for Cross-Site Request Forgery. It was rather popular in the earlier internet but now it's almost a non-issue thanks to standard prevention mechanisms built into most of popular web frameworks. The forgery is to make user click on a form that will send a cross-site request. The protection is to check that the request didn't come from a third-party site. CORS stands for Cross-Origin Resource Sharing. It's a part of HTTP specification that describes how to permit certain cross-site requests. This includes preflight requests and response headers that state which origins are allowed to send requests. So, by default, are cross-origin requests allowed and we need CSRF protection, or they are forbidden and we need CORS to allow them? The answer is both. The default behaviour The default behaviour is defined by Same-origin policy, and is enforced by browsers. The policy states that, generally speaking, cross-site writes are allowed, and cross-site reads are not. You can send a POST request by submitting a form, you browser won't let you read the response of it. There is a newer part of this spec that sort of solves CSRF. In 2019, there was an initiative to change default cookies behaviour. Before that, cookies were always sent in cross-site requests. The default was changed to not send cookies in cross-site POST requests. To do that, a new SameSite attribute for the set-cookie header was introduced. The attribute value to make the old default is None, and the new default would be Lax. In 2025, 96% browsers support the SameSite attribute, and 75% support the new default. Notably, Safari haven't adopted the default, and UCBrowser doesn't support any nice things. Sidenote: I can't understand how UCBrowser remains relatively popular among users, given that there are settings in js builders to build for N% of the users and next to nobody puts 99% there. Sidenote 2: Origin is not the same as Site. Origin is a combination of a scheme, a hostname, and a port. Site is a combination of scheme and effective top level domain + 1. Subdomains and ports don't matter for sites. Links: Same-origin policy | caniuse SameSite cookie attribute CORS CORS is a way to override the same origin policy per origin. The spec describes a certain browser-server interaction. Browser sends preflight requests of type OPTIONS before actual requests, server replies with rules for the origin. The rules are in a form of response headers. The rules may specify if the reply can be read, if headers can be sent and received, allowed HTTP methods. Header names start with Access-Control. Browser then follows the rules. CORS applies for several types of the requests: * js-initiated fetch and XMLHttpRequest * web fonts * webgl textures * images/video frames drawn to a canvas using drawImage * css shapes from images What is notoriously not in this list is form submissions, otherwise known as simple requests. This is part of the internet being backward-compatible: The motivation is that the