whatwg/fetch

Tighten `application/x-www-form-urlencoded` CORS safe-list carveout?

domfarolino opened this issue · 3 comments

Right now cross-origin POST requests with the Content-Type: application/x-www-form-urlencoded header are safe-listed, and thus don't trigger CORS preflight requests. I believe this is to grandfather-in the fact that you could always make these requests with <form method=post> before preflight requests were a thing. However, my understanding is that we generally want these kinds of non-form-initiated requests to require preflights, hence the fact that we require preflights for other content types.

But other specs can simply use the Content-Type: application/x-www-form-urlencoded request header to avoid preflights on a request that really should send preflights. In fact, my understanding is that FedCM did this on accident (the spec was not trying to bypass the preflight requirement, they just thought it was the most sensible value). However I think it is Fetch's intention to require preflights for these kinds of requests (since they're "new", and not HTML form-initiated), so I'm wondering if we should change Fetch (and its implementations) to actually require preflight requests for POSTs even if they have the Content-Type: application/x-www-form-urlencoded request header, but if they are not specifically triggered by actual HTML forms.I'm now sure how Fetch would check this — I assumed we could check "initiator" but there doesn't seem to be a value for forms specifically.

I think that would prevent consumers from using this content-type on new, non-form-initiated requests while accidentally bypassing preflight requests without realizing it. Rather, these requests would get a preflight, because they aren't initiated from HTML forms and therefore shouldn't be grandfathered-in in the same way that HTML forms are.

Thoughts?

I think that would break service workers. Unless you add more shenanigans.

See also #838 for another tightening idea.

(You might also be interested in annevk/orb#18.)

Yeah that's a good point. I guess the other shenanigans would be keeping the current carve-out behavior for service-worker-forwarded requests only if they came from a <form>? And I don't think we have all that information in a single request object, so that's probably a deal-breaker.

We do, both request's mode and destination give it away. But this exception has been there since the dawn of cross-origin XMLHttpRequest and I strongly suspect it's used. Not sure why I didn't gave that rationale in the earlier comment, maybe it escaped me. (It was also very much intentional to allow that without preflight contrary to what OP suggests.)

(By the way, the grandfather clause is probably best avoided given its origin: https://en.wikipedia.org/wiki/Grandfather_clause.)