415

Cross-origin resource sharing is a mechanism that allows a web page to make XMLHttpRequests to another domain (from wikipedia).

I've been fiddling with CORS for the last couple of days and I think I have a pretty good understanding of how everything works.

So my question is not about how CORS / preflight work, it's about the reason behind coming up with preflights as a new request type. I fail to see any reason why server A needs to send a preflight (PR) to server B just to find out if the real request (RR) will be accepted or not - it would certainly be possible for B to accept/reject RR without any prior PR.

After searching quite a bit I found this piece of information at www.w3.org (7.1.5):

To protect resources against cross-origin requests that could not originate from certain user agents before this specification existed a preflight request is made to ensure that the resource is aware of this specification.

I find this is the hardest to understand sentence ever. My interpretation (should better call it 'best guess') is that it's about protecting server B against requests from server C that is not aware of the spec.

Can someone please explain a scenario / show a problem that PR + RR solves better than RR alone?

isherwood
  • 46,000
  • 15
  • 100
  • 132
jan groth
  • 12,429
  • 5
  • 34
  • 51

9 Answers9

353

I spent some time being confused as to the purpose of the preflight request but I think I've got it now.

The key insight is that preflight requests are not a security thing. Rather, they're a not-changing-the-rules thing.

Preflight requests have nothing to do with security, and they have no bearing on applications that are being developed now, with an awareness of CORS. Rather, the preflight mechanism benefits servers that were developed without an awareness of CORS, and it functions as a sanity check between the client and the server that they are both CORS-aware. The developers of CORS felt that there were enough servers out there that were relying on the assumption that they would never receive, e.g. a cross-domain DELETE request that they invented the preflight mechanism to allow both sides to opt-in. They felt that the alternative, which would have been to simply enable the cross-domain calls, would have broken too many existing applications.

There are three scenarios here:

  1. Old servers, no longer under development, and developed before CORS. These servers may make assumptions that they'll never receive e.g. a cross-domain DELETE request. This scenario is the primary beneficiary of the preflight mechanism. Yes these services could already be abused by a malicious or non-conforming user agent (and CORS does nothing to change this), but in a world with CORS the preflight mechanism provides an extra 'sanity check' so that clients and servers don't break because the underlying rules of the web have changed.

  2. Servers that are still under development, but which contain a lot of old code and for which it's not feasible/desirable to audit all the old code to make sure it works properly in a cross-domain world. This scenario allows servers to progressively opt-in to CORS, e.g. by saying "Now I'll allow this particular header", "Now I'll allow this particular HTTP verb", "Now I'll allow cookies/auth information to be sent", etc. This scenario benefits from the preflight mechanism.

  3. New servers that are written with an awareness of CORS. According to standard security practices, the server has to protect its resources in the face of any incoming request -- servers can't trust clients to not do malicious things. This scenario doesn't benefit from the preflight mechanism: the preflight mechanism brings no additional security to a server that has properly protected its resources.

Michael Iles
  • 4,109
  • 2
  • 16
  • 17
  • 17
    If that is the case why is it sent on every request? One request per server should be adequate to determine if the server is aware of CORS. – Douglas Ferguson Jan 05 '15 at 03:41
  • 3
    The spec includes a [preflight-result-cache](http://www.w3.org/TR/cors/#preflight-result-cache) in the browser. So, while it still feels kludgy and ineffective security, it seems possible to configure new servers to have the preflight cached indefinitely. – Michael Cole Feb 03 '15 at 03:33
  • 9
    I agree that preflight requests aren't inherently related to security, but it sounds like CORS' use of preflight requests is definitely for security reasons. It's more than just a sanity check to prevent a relatively harmless error scenario. If the user agent blindly sent the request to the server, falsely assuming the server implemented CORS, it would most likely be accepting cross site request forgeries. Even though the response wouldn't be readable by javascript, the server may have already taken some undesirable action like delete an account or make a bank transfer. – Alexander Taylor Mar 18 '15 at 16:43
  • Sometimes It would be hard for the client to know what "one request per server" is. Even the exact same URL could go to multiple different physical servers when requested multiple times. One of those servers might be misconfigured so that CORS isn't enabled, and if it is, cross site request forgery could be possible simply by repeatedly sending your request until it got randomly chosen for the misconfigured server. Sometimes the server depends on the URL, so you have Apache running on /app1 and Jetty running on /app2. – Alexander Taylor Mar 18 '15 at 16:48
  • 6
    The problem is, the preflight-result-cache is basically useless because 1. it applies only to the exact request, not the entire domain, so all requests are going to preflight the first time anyways; and 2. as implemented, it's limited to 10 minutes in most browsers, so not even close to indefinitely. – davidgoli Jan 22 '16 at 01:49
  • Is there not a security benefit around cookies? If banking website (A) has a RESTful API that accepts cookies for authentication and the user has a cookie for (A), malicious website (B) could make an XHR CORS request to that API that includes (A)'s cookies. The javascript running on (B) doesn't have direct access to (A)'s cookies in its javascript and would never be able to get it server side, but the browser includes it in the CORS request to (A). – Technetium Jun 10 '16 at 16:31
  • Sooo if I'm building a new REST API, I'm in scenario #3, correct? – rinogo Jul 28 '16 at 23:29
  • Why chrome make an option request to prior to all post request? As you said not all servers can handle such requests – Vikas Bansal Aug 10 '16 at 13:27
  • @AlexanderTaylor Agreed: they clearly are for security, but they seem like they provide a false sense of security to me... – Miles Rout Feb 13 '17 at 02:43
  • 2
    @VikasBansal The existing server has to "opt in" and agree to share their resources across origins by configuring how they reply to the preflight option request. If they don't answer to the preflight request explicitly, the browser will not issue the actual request. Not all servers will want to entertain cross-origin requests after all. – Kevin Lee May 23 '17 at 16:55
  • About scenario #1 - if the purpose of allowing "simple" requests is to allow old, and unmaintained servers to keep working (as the preflight-triggering actions were not allowed prior CORS), how come the browser still look for "access-control-allow-origin" header in the response, even for simple requests? – Amico Feb 06 '18 at 17:40
  • 1
    3rd paragraph : how would allowing cross-domain calls break anything at all ? I can't make sense out of that... If anything, it should *fix* apps that use cross-domain calls. (though I agree that would not be secure) – Sindarus May 11 '19 at 17:49
  • CORS still sound like a terrible idea. it instead cripples future apps. people simply shouldn't be calling foreign APIs without knowing if they will work! – symbiont Jun 19 '20 at 12:48
  • "Preflight requests have nothing to do with security" - I disagree. Without a preflight request, a server not aware of CORS would accept a DELETE request, for example, thinking it would never receive a DELETE request from cross-origin due to the same origin policy. The preflight prevents malicious websites doing a CSRF attack using a DELETE/PUT request. – David Klempfner Nov 09 '20 at 12:36
  • are preflight triggered for same origin? – Muhammad Umer Apr 17 '21 at 19:57
268

What was the motivation behind introducing preflight requests?

Preflight requests were introduced so that a browser could be sure it was dealing with a CORS-aware server before sending certain requests. Those requests were defined to be those that were both potentially dangerous (state-changing) and new (not possible before CORS due to the Same Origin Policy). Using preflight requests means that servers must opt-in (by responding properly to the preflight) to the new, potentially dangerous types of request that CORS makes possible.

That's the meaning of this part of the original specification: "To protect resources against cross-origin requests that could not originate from certain user agents before this specification existed a preflight request is made to ensure that the resource is aware of this specification."

Can you give me an example?

Let's imagine that a browser user is logged into their banking site at A.com. When they navigate to the malicious B.com, that page includes some Javascript that tries to send a DELETE request to A.com/account. Since the user is logged into A.com, that request, if sent, would include cookies that identify the user.

Before CORS, the browser's Same Origin Policy would have blocked it from sending this request. But since the purpose of CORS is to make just this kind of cross-origin communication possible, that's no longer appropriate.

The browser could simply send the DELETE and let the server decide how to handle it. But what if A.com isn't aware of the CORS protocol? It might go ahead and execute the dangerous DELETE. It might have assumed that—due to the browser's Same Origin Policy—it could never receive such a request, and thus it might have never been hardened against such an attack.

To protect such non-CORS-aware servers, then, the protocol requires the browser to first send a preflight request. This new kind of request is something that only CORS-aware servers can respond to properly, allowing the browser to know whether or not it's safe to send the actual DELETE.

Why all this fuss about the browser, can't the attacker just send a DELETE request from their own computer?

Sure, but such a request won't include the user's cookies. The attack that this is designed to prevent relies on the fact that the browser will send cookies (in particular, authentication information for the user) for the other domain along with the request.

That sounds like Cross-Site Request Forgery, where a form on site B.com can be submitted to A.com with the user's cookies and do damage.

That's right. Another way of putting this is that preflight requests were created so as to not increase the CSRF attack surface for non-CORS-aware servers.

But POST is listed as a method that doesn't require preflights. That can change state and delete data just like a DELETE!

That's true! CORS does not protect your site from CSRF attacks. Then again, without CORS you are also not protected from CSRF attacks. The purpose of preflight requests is just to limit your CSRF exposure to what already existed in the pre-CORS world.

Sigh. OK, I grudgingly accept the need for preflight requests. But why do we have to do it for every resource (URL) on the server? The server either handles CORS or it doesn't.

Are you sure about that? It's not uncommon for multiple servers to handle requests for a single domain. For example, it may be the case that requests to A.com/url1 are handled by one kind of server and requests to A.com/url2 are handled by a different kind of server. It's not generally the case that the server handling a single resource can make security guarantees about all resources on that domain.

Fine. Let's compromise. Let's create a new CORS header that allows the server to state exactly which resources it can speak for, so that additional preflight requests to those URLs can be avoided.

Good idea! In fact, the header Access-Control-Policy-Path was proposed for just this purpose. Ultimately, though, it was left out of the specification, apparently because some servers incorrectly implemented the URI specification in such a way that requests to paths that seemed safe to the browser would not in fact be safe on the broken servers.

Was this a prudent decision that prioritized security over performance, allowing browsers to immediately implement the CORS specification without putting existing servers at risk? Or was it shortsighted to doom the internet to wasted bandwidth and doubled latency just to accommodate bugs in a particular server at a particular time?

Opinions differ.

Well, at the very least browsers will cache the preflight for a single URL?

Yes. Though probably not for very long. In WebKit browsers the maximum preflight cache time is currently 10 minutes.

Sigh. Well, if I know that my servers are CORS-aware, and therefore don't need the protection offered by preflight requests, is there any way for me to avoid them?

Your only real option is to make sure that your requests use CORS-safe methods and headers. That might mean leaving out custom headers that you would otherwise include (like X-Requested-With), changing the Content-Type, or more.

Whatever you do, you must make sure that you have proper CSRF protections in place, since CORS will not block all unsafe requests. As the original specification puts it: "resources for which simple requests have significance other than retrieval must protect themselves from Cross-Site Request Forgery".

Kevin Christopher Henry
  • 37,093
  • 5
  • 98
  • 87
  • When you say "Since the user is logged into A.com, that request, if sent, would include cookies that identify the user." why would a request from tab B include the cookies from tab A, tabs are usually (at least in Chrome) separate processes in browsers? – Yos Jul 20 '19 at 18:19
  • 1
    @Yos: The browser would include those cookies because that's how browsers are expected to work (as codified in standards like [RFC 6265](https://tools.ietf.org/html/rfc6265#section-5.4)). Whether or not a browser uses separate processes for tabs is an implementation detail, it won't keep it from sending cookies. – Kevin Christopher Henry Jul 21 '19 at 01:58
  • @KevinChristopherHenry `When they navigate to the malicious B.com, that page includes some Javascript that tries to send a DELETE request to A.com/account. Since the user is logged into A.com, that request, if sent, would include cookies that identify the user. Before CORS, the browser's Same Origin Policy would have blocked it from sending this request.` -> why would browsers block the DELETE request triggered from same domain (i.e) DELETE request is triggered from A.com !!? this paragraph is confusing to me..please clarify.. – divine Nov 26 '19 at 03:00
  • 1
    @divine: It's not triggered by the same domain, it's a request to `A.com` triggered by Javascript from a page at `B.com`. – Kevin Christopher Henry Nov 26 '19 at 05:37
  • @KevinChristopherHenry You said - `To protect such non-CORS-aware servers, then, the protocol requires the browser to first send a preflight request`. Now, let's assume we don't have preflight request. Still there will be no problem. The non-CORS-aware server will never send `Access-Control-Allow-Origin` header in response (as it is not aware of such header) and a normal CORS request by browser to such a server will be automatically dropped as above header won't be present in response , is not it ? – Number945 Dec 17 '20 at 21:17
  • 1
    @Number945: The paragraph before that explains the problem. The danger is that the server might execute the `DELETE` if the browser allows it to be sent. That's the problem we're trying to prevent with preflights. For safe requests we don't have to protect the server, so in that case preflights aren't required and the browser can just rely on the headers to decide what to do. – Kevin Christopher Henry Dec 18 '20 at 00:32
  • @KevinChristopherHenry One more doubt. What was the logic behind having a preflight on simple POST request but with upload event ? A simple POST does not need it though. Upload event is purely client side. So, why preflight for that ? – Number945 Dec 19 '20 at 17:52
  • @Number945: That's a good question. The spec [clearly states](https://xhr.spec.whatwg.org/#event-listeners-and-preflight) that that is the case, but doesn't explain the reasoning. You might want to post a separate question. – Kevin Christopher Henry Dec 19 '20 at 18:28
  • "Before CORS, the browser's Same Origin Policy would have blocked it from sending this request.": I think it does not block it from being sent, only the data from being read back in JavaScript so you can't read back the Synchronizer token, see also: https://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important/72569#72569 And so the sever must use Synchronizer token. – Ciro Santilli新疆棉花TRUMP BAN BAD Apr 01 '21 at 20:40
  • 1
    @CiroSantilli新疆棉花TRUMPBANBAD: It would block it, because it's a `DELETE`. The examples you linked to are using `POST` and `GET`, which would not normally be blocked, and which I discuss later in the answer. – Kevin Christopher Henry Apr 01 '21 at 20:53
  • OK! So it seems DELETE used to get blocked before CORS, but POST didn't. It would be good to try to clarify the rationale of why things were like that. – Ciro Santilli新疆棉花TRUMP BAN BAD Apr 01 '21 at 21:07
58

Consider the world of cross-domain requests before CORS. You could do a standard form POST, or use a script or an image tag to issue a GET request. You couldn't make any other request type other than GET/POST, and you couldn't issue any custom headers on these requests.

With the advent of CORS, the spec authors were faced with the challenge of introducing a new cross-domain mechanism without breaking the existing semantics of the web. They chose to do this by giving servers a way to opt-in to any new request type. This opt-in is the preflight request.

So GET/POST requests without any custom headers don't need a preflight, since these requests were already possible before CORS. But any request with custom headers, or PUT/DELETE requests, do need a preflight, since these are new to the CORS spec. If the server knows nothing about CORS, it will reply without any CORS-specific headers, and the actual request will not be made.

Without the preflight request, servers could begin seeing unexpected requests from browsers. This could lead to a security issue if the servers weren't prepared for these types of requests. The CORS preflight allows cross-domain requests to be introduced to the web in a safe manner.

monsur
  • 39,509
  • 15
  • 93
  • 91
  • How do you make a POST request via script/img tag? – freakish Mar 13 '13 at 16:33
  • 2
    You can't. I meant that you could either do a form POST, *OR* do a GET using script/img. I edited the post to hopefully clarify this. – monsur Mar 13 '13 at 16:35
  • 6
    Thanks for the answer, that certainly completed my picture! Unfortunately I still fail to see the central point behind preflights. Regarding your answer: What would an '_unexpected request_' be? How would it be any 'more' unexpected / less safe in a non-preflight world than it is in a preflight world (with eg a lost preflight or a malicious browser that simply 'forgets' about preflighting)? – jan groth Mar 16 '13 at 00:32
  • CORS is all about trust. The server trusts the user-agent to send the correct headers, and if it doesn't, it is a bug or something malicious. So you have to assume you can trust your browser, and that your browser won't do anything wonky like drop a preflight. – monsur Mar 20 '13 at 02:53
  • 10
    There are probably APIs out there which rely on the browser's same-origin policy to protect their resources. They should have additional security, but they rely on the same-origin policy instead. Without the preflight, a user on a different domain could now issue a request to the API. The API would assume the request is valid (since it knows nothing of CORS) and execute the request. The browser could block the response from reaching the user, but at this point, the damage may already be done. If the request was a PUT/DELETE, the resource may have been updated or deleted. – monsur Mar 20 '13 at 02:55
  • It's not clear to me why the CORS new mechanism, as there seemed to be an existing one that would have served the preflight purpose just fine. The book "RESTful Web Services" describes a "Look-Before-You-Leap" request using only existing standards (and browser enhancements)-- The analogue of the preflight has no entity body and the additional header Expect: 100-continue. If the request would be okay, the server returns 100 ("continue") and the browser then sends the "real" request with its body. If the request would be rejected, the server returns 417 ("expectation failed"). – Chuck Kollars Apr 01 '13 at 18:48
  • @monsur Does it mean for those "APIs out there which rely on the browser's same-origin policy", it is not protected against any non-browser clients? Why browser is particularly important in such scenarios? When it comes to attacking, the attacker should know this fairly well to by-pass that limitation. Have I missed something? Thanks. – Devs love ZenUML Jun 02 '20 at 06:10
  • 1
    @Xiao Peng - ZenUML.com the attacker would some how have to get the victim to be using a malicious browser. Most people use well known safe browsers these days. – David Klempfner Sep 25 '20 at 00:52
  • @DavidKlempfner, when you say "get the **victim** to be using a malicious browser", do you mean it is to protect the users instead of the service (server)? – Devs love ZenUML Sep 25 '20 at 01:04
  • 1
    @Xiao Peng - ZenUML.com it protects both. If a xsrf attack is prevented and a bank therefore does not delete a customer's account, then both the customer/user and the bank are happy. – David Klempfner Sep 25 '20 at 01:37
39

CORS allows you to specify more headers and method types than was previously possible with cross-origin <img src> or <form action>.

Some servers could have been (poorly) protected with the assumption that a browser cannot make, e.g. cross-origin DELETE request or cross-origin request with X-Requested-With header, so such requests are "trusted".

To make sure that server really-really supports CORS and not just happens to respond to random requests, the preflight is executed.

Kornel
  • 91,239
  • 30
  • 200
  • 278
  • 12
    This should have been the accepted answer. It is the most unambiguous and to-the-point. In essence the only point of preflight requests are to integrate pre-CORS Web standards with post-CORS Web standards. – chopper draw lion4 Feb 15 '16 at 10:29
  • 2
    I like this answer, but I feel it can't be the full reason... the "assumption of trust" must have applied only to things that only the browser could do (specifically, sending the browser's user information restricted to their domain - that is, cookies). If that was not a part of the assumption, then anything a cross-origin browser request can do could already be done by a 3rd-party, non-browser agent, right? – Fabio Beltramini Jul 21 '17 at 21:39
  • 2
    @FabioBeltramini Right, non-browsers can send anything they want. However, attacks via browsers are special because you can make other people's browsers do things, from their own IP, with their own cookies, etc. – Kornel Jul 24 '17 at 19:46
  • I start seeing the real problem. Thanks for the comments and the reply @FabioBeltramini and Kronel's reply. If the pre-flight check is not there, an attacker would be able to put some JavaScript code on his site but executed from many other people's computers. All other clients are kind of difficult to 'hire' others to do this, including mobile Apps. – Devs love ZenUML Jun 02 '20 at 06:18
17

Here's another way of looking at it, using code:

<!-- hypothetical exploit on evil.com -->
<!-- Targeting banking-website.example.com, which authenticates with a cookie -->
<script>
jQuery.ajax({
  method: "POST",
  url: "https://banking-website.example.com",
  data: JSON.stringify({
    sendMoneyTo: "Dr Evil",
    amount: 1000000
  }),
  contentType: "application/json",
  dataType: "json"
});
</script>

Pre-CORS, the exploit attempt above would fail because it violates the same-origin policy. An API designed this way did not need XSRF protection, because it was protected by the browser's native security model. It was impossible for a pre-CORS browser to generate a cross-origin JSON POST.

Now CORS comes on the scene – if opting-in to CORS via pre-flight was not required, suddenly this site would have a huge vulnerability, through no fault of their own.

To explain why some requests are allowed to skip the pre-flight, this is answered by the spec:

A simple cross-origin request has been defined as congruent with those which may be generated by currently deployed user agents that do not conform to this specification.

To untangle that, GET is not pre-flighted because it is a "simple method" as defined by 7.1.5. (The headers must also be "simple" in order to avoid the pre-flight). The justification for this is that "simple" cross-origin GET request could already be performed by e.g. <script src=""> (this is how JSONP works). Since any element with a src attribute can trigger a cross-origin GET, with no pre-flight, there would be no security benefit to requiring pre-fight on "simple" XHRs.

Dylan Tack
  • 626
  • 5
  • 8
  • 1
    @MilesRout: Telnet isn't part of the threat model that preflights aim to mitigate. Preflight is relevant to browsers that 1) Rely on stored, "ambient authority" (e.g. cookies), and 2) can be tricked into misusing that authority by a third-party (e.g. cross-site request forgery). The generalized model is known as the [confused deputy problem](https://en.wikipedia.org/wiki/Confused_deputy_problem). – Dylan Tack May 16 '17 at 00:42
  • It's not that there would be no security benefit to requiring preflight on simple XHRs, it's that doing so would break the rules. Suddenly GET requests that worked before, would no longer work. – David Klempfner Nov 09 '20 at 12:22
14

I feel that the other answers aren't focusing on the reason pre-fight enhances security.

Scenarios:

1) With pre-flight. An attacker forges a request from site dummy-forums.com while the user is authenticated to safe-bank.com
If the Server does not check for the origin, and somehow has a flaw, the browser will issue a pre-flight request, OPTION method. The server knows none of that CORS that the browser is expecting as a response so the browser will not proceed (no harm whatsoever)

2) Without pre-flight. An attacker forges the request under the same scenario as above, the browser will issue the POST or PUT request right away, the server accepts it and might process it, this will potentially cause some harm.

If the attacker sends a request directly, cross origin, from some random host it's most likely one is thinking about a request with no authentication. That's a forged request, but not a xsrf one. so the server has will check credentials and fail. CORS doesn't attempt to prevent an attacker who has the credentials to issue requests, although a whitelist could help reduce this vector of attack.

The pre-flight mechanism adds safety and consistency between clients and servers. I don't know if this is worth the extra handshake for every request since caching is hardy use-able there, but that's how it works.

Hirako
  • 199
  • 2
  • 5
  • Agree on the CSRF attack issue that is still possible against "new servers" mentioned in @michael-iles 's reply. – eel ghEEz Oct 14 '15 at 20:17
  • 1
    But why some requests like POST with Content-Type text/plain doesn't do a pre-flight request? In my head, every 'write' request (POST, PUT, DELETE) should have this pre-flight request if security is an issue. – Israel Fonseca Sep 14 '16 at 19:54
  • POST with text/plain is considered a simple request - note that the browser will not display the response if the origin does not match (which would be the case if the server is not configured for CORS). – Hirako Sep 16 '16 at 00:15
  • On the attacking side, there are interesting things that can be done, exploiting the fact simple requests are tolerated and will be sent by most browsers. e.g [this](http://pentestmonkey.net/blog/csrf-xml-post-request). – Hirako Sep 16 '16 at 00:24
  • @Hirako the browser might not display the response if the origin header value is a different domain but the damage would still be done. – David Klempfner Nov 09 '20 at 12:24
3

Additionally, for HTTP request methods that can cause side-effects on user data (in particular, for HTTP methods other than GET, or for POST usage with certain MIME types), the specification mandates that browsers "preflight" the request

Source

Oliver Weichhold
  • 9,318
  • 5
  • 41
  • 80
2

In a browser supporting CORS, reading requests (like GET) are already protected by the same-origin policy: A malicious website trying to make an authenticated cross-domain request (for example to the victim's internet banking website or router's configuration interface) will not be able to read the returned data because the bank or the router doesn't set the Access-Control-Allow-Origin header.

However, with writing requests (like POST) the damage is done when the request arrives at the webserver.* A webserver could check the Origin header to determine if the request is legit, but this check is often not implemented because either the webserver has no need for CORS or the webserver is older than CORS and is therefore assuming that cross-domain POSTs are completely forbidden by the same-origin policy.

That is why webservers are given the chance to opt-in into receiving cross-domain write requests.

* Essentially the AJAX version of CSRF.

AndreKR
  • 28,030
  • 13
  • 86
  • 146
  • "the webserver is older than CORS and is therefore assuming that cross-domain POSTs are completely forbidden by the same-origin policy." Cross-domain POSTs have always been allowed. You just can't view the response. "That is why webservers are given the chance to opt-in into receiving cross-domain write requests." - They are only able to opt-in to PUT/DELETE requests (or GET/POST with non standard headers). A simple POST request would be allowed, with or without an awareness of CORS. – David Klempfner Nov 09 '20 at 12:29
  • @DavidKlempfner I wasn't aware of that and I wonder why it's allowed. Probably because disallowing it would break too many existing solutions (like links to a search result obtained by POST) and without credentials it was deemed relatively safe. – AndreKR Apr 08 '21 at 11:01
  • 1
    this explains it: https://stackoverflow.com/questions/64769030/why-does-the-same-origin-policy-not-block-post-requests – David Klempfner Apr 08 '21 at 22:51
1

Aren't the preflighted requests about Performance? With the preflighted requests a client can quickly know if the operation is allowed before send a large amount of data, e.g., in JSON with PUT method. Or before travel sensitive data in authentication headers over the wire.

The fact of PUT, DELETE, and other methods, besides custom headers, aren't allowed by default(They need explicit permission with "Access-Control-Request-Methods" and "Access-Control-Request-Headers"), that sounds just like a double-check, because these operations could have more implications to the user data, instead GET requests. So, it sounds like:

"I saw that you allow cross-site requests from http://foo.example, BUT are you SURE that you'll allow DELETE requests? Did you consider the impacts that these requests might cause in the user data?"

I didn't understand the cited correlation between the preflighted requests and the old servers benefits. A Web Service that was implemented before CORS, or without a CORS awareness, will never receive ANY cross-site request, because first their response won't have the "Access-Control-Allow-Origin" header.

Nipo
  • 131
  • 1
  • 9
  • 4
    You're misunderstanding Access-Control-Allow-Origin. An absence of that header doesn't prevent the browser from sending requests, it merely prevents JS from being able to read the data in the response. – Dylan Tack Jul 09 '15 at 03:22
  • Could you explain this 'An absence of that header doesn't prevent the browser from sending requests, it merely prevents JS from being able to read the data in the response' again, I din't get it completely. – bhagwans Jan 25 '16 at 06:13
  • @DylanTack Good point. This makes me wonder though, why is a GET xhr not being preflight as well? Although unlikely, GET requests could be harmful/data-mutating as well. Also, since all this could be solved with CSRF, this seems to me like the browser is being over-protective of servers that are too negligent to implement common security practices. – Peleg May 04 '16 at 16:52
  • The accepted answer explains it well, as a "not-changing-the-rules thing" (backwards-compatibility with web sites created before CORS existed). Still it's interesting to see code, so I've posted another answer with a code example. – Dylan Tack May 05 '16 at 01:03