1

I understand that cross-origin, "simple" requests, like GET and POST have always been allowed (but you just can't view the response), and that PUT/DELETE are blocked, or preflighted if your browser supports CORS.

I understand that allowing a GET request to be sent is harmless, as long as the response is blocked, because GET requests should be safe/idempotent (if not, that's the developer's fault for not making their API ReSTful).

I also understand from this answer, that GET and POST are typical/intentional requests made by users, eg when typing something into the URL textbox or clicking a button to post a form.

But why would a browser allow a cross-origin POST request using xhr?

So what if the user can make intentional POST requests by clicking on a button to post a form? Allowing javascript to send a POST request is a recipe for disaster, any malicious page that loads could execute a cross-origin POST request behind the scenes.

Why didn't browsers prevent this from the beginning?

If they did, then now that CORS is around, POST requests could be preflighted just like PUT/DELETE and you'd have fewer xsrf attacks.

David Klempfner
  • 6,679
  • 15
  • 47
  • 102

1 Answers1

3

Eliminating the ability to use POST would have drastically reduced the capabilities of web applications without providing a significant increase in security.

Without POST there would have been no way to request that another domain modify data. (Remember, this is before CORS offered a way to opt in to cross-domain requests.) That eliminates whole classes of useful web applications. (Or, more likely, web applications would have worked around this problem by abusing GET.)

And you wouldn't get much in return for this sacrifice. Any server that could be harmed by a cross-domain XHR POST would already have to have CSRF protections in place to deal with cross-domain attacks from a form POST. And such defenses (like requiring a special token) are equally effective against both.

Kevin Christopher Henry
  • 37,093
  • 5
  • 98
  • 87
  • "Without POST there would have been no way to request that another domain modify data." Couldn't you use the same logic with PUT and DELETE but replace "modify" with "update" and "delete"? I get that you can update and delete in a post anyway, but still, if you're going to allow POST, then why not allow the other two as well? – David Klempfner Nov 10 '20 at 22:12
  • 3
    @DavidKlempfner: The reason not to allow `PUT` and `DELETE` in Javascript (and the reason why they require preflights with CORS) is that you can't use them with a form, and the goal is to limit CSRF exposure to what is already possible without Javascript. As to why forms didn't allow `PUT` and `DELETE` in the first case, I'm not sure. If I had to guess I'd say no one saw much need for them. This was before REST. And according to [this history](https://softwareengineering.stackexchange.com/a/211790/112291), not everyone agrees they'd even be useful in forms. – Kevin Christopher Henry Nov 10 '20 at 22:27
  • Why limit CSRF to what is already possible without Javascript? Why not go one step further, make things more secure by disallowing code to run when you load a malicious page that could make a POST request behind the scenes as soon as the page loads? At least with a form the user has to purposely click on a button. Are there any issues with allowing a POST from a form with a button but disallowing that same POST request from javascript? – David Klempfner Nov 10 '20 at 23:08
  • 2
    @DavidKlempfner: I'm not sure how that's different from your original question. The issue with doing that is that it greatly limits the range of possible web applications while allowing little to no security benefit. A server can't assume that a malicious third-party page won't trigger a form submission, therefore it must have CSRF protections in place. And if it does it will also be protected against malicious third-party scripts. – Kevin Christopher Henry Nov 11 '20 at 01:04