Let's say there's a hypothetical email site called email.com
, and an evil site called evil.com
. email.com
sends the emails using POST requests.
A user that has session cookies of email.com
saved on their computer visits evil.com
, and evil.com
sends a http POST
request to email.com
that sends a scam email. As far as I understand the server would send the email from the user's account without making any checks, since the browser provided the session cookies with the request and preflight checks don't apply to POST
, and then even if CORS doesn't share the response from email.com
with evil.com
because it's Access-Control-Allow-Origin
doesn't include evil.com
it wouldn't matter, because the email would already be sent.
I know this could be prevented by using for example a CSRF token, but why aren't preflight checks just implemented for POST
requests too?
CodePudding user response:
You claim that
preflight checks don't apply to
POST
but that is incorrect: so-called simple requests that happen to use the POST
method don't get preflighted, but non-simple POST
requests do get preflighted.
As an example, the following script run in the context of any Web origin other than https://google.com
will trigger CORS preflight because, according to the Fetch standard (which contains the de facto CORS specification), X-Foo
is not a CORS-safelisted request header:
let opts = {
method: "POST",
headers: {
"X-Foo": "foo"
}
};
fetch("https://google.com", opts);
Besides, CORS preflight was never intended as a defence mechanism against CSRF; this belief is a common misconception. Rather, preflight's purpose is to protect servers that predate the advent of browsers' support for cross-origin requests. See this more complete answer for more details about the rationale behind CORS preflight.