4 ms·
Why's it strange? In a properly designed application, it shouldn't do anything any different to the no-cors requests you can already achieve with e.g. an <img>
by lol768 7y ago
Why's it strange? In a properly designed application, it shouldn't do anything any different to the no-cors requests you can already achieve with e.g. an <img> element. HEAD, GET et al are all supposed to be "safe methods" per the spec.
- homakov 7y agoYou can't achieve a HEAD request with <img> elements, can you? In a rails env the only way to upgrade to non-standard methods (PATCH, PUT etc) were always to supply _method and pass CSRF protection first. This trick is clearly a bypass because it instructs browser to make a HEAD request, something it never did before. If you try to make other non-standard request you will get this error: Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'Window': 'PATCH' is unsupported in no-cors mode.
- lol768 7y agoNo, but you can achieve a GET which is also a "safe request method" per RFC7231. All of these requests should be idempotent. I'm not a fan of the hacks that exist to allow HTML forms to emulate other request methods. They're off by default in ASP.NET Core MVC, which is good IMO.
- homakov 7y ago"should". Real apps are much more complicated than what they are in theory. In theory all CSRF protections must be based on an auth token, in practice they routinely rely on the method or referrer. For this reason browser upgrades must be extremely careful to not break older protections. That's why you cannot set your own referer (which is supposed to mean nothing), you cannot supply Content-type: application/json unless instructed by CORS preflight, etc etc. Here, the backwards compatibility was clearly broken. It was never possible to send HEAD few years ago with regular XHR or <img>s. Web standards owe $25k back to github. Yes, github's routing was flawed but it wasn't exploitable until browsers allowed HEAD in fetch() no-cors mode.
- lol768 7y ago>For this reason browser upgrades must be extremely careful to not break older protections. It's too late for that though. We've already had e.g. Referrer-Policy come and break existing CSRF protection which treated an empty/missing Referer header as 'safe'. You're right that bad assumptions are going to made all over the place in the real world, but browser vendors shouldn't shoulder all of that responsibility. You have to draw the line somewhere, right?
- homakov 7y agoI worked a lot with client side bugs earlier, and clearly this trick has crossed this line. Browsers cannot say in one scenario that "content-type:application/json" are unsafe and in another allow completely unnecessary HEAD method that nobody ever used to be sent with 3rd party JS page. Seriously who needs HEAD in their client side development? It's purely a technical method w/o clear use pattern. It's not even valid in <form method=""> so why would it be valid in fetch()? Oh and PATCH/PUT are still invalid in fetch(). We're lucky that this code pattern is only common in Rails. Otherwise it could open a whole class of bugs.
- thinkloop 7y agoWait, why is it useless? At minimum there is the example cited in the article of checking file length without having to download the actual file, but more generally, if headers have any value, and they must since they exist, why can't you imagine situations where you just want to see the headers without downloading a giant body?
- homakov 7y agoFor a client side code running on 3rd party page, there is no use case to let it send HEAD to you. Only GET and POST should be allowed by default, other methods only through CORS preflight. That was the premise of CORS. They broke it.
- 7y ago
- yxhuvud 7y agoI'm also not a fan of them, but I am even less a fan of the HTML spec for forms not supporting all methods.
- jraph 7y agoBut if your form is an advanced search form of instance, it should lead to a get request in my opinion.
- gcbw3 7y agoHTTP is dead. No developer today understand anything from HTTP and even cookies and cache are already too complex and hidden from most (just like memory management!) But that will solve itself when we all move to http3 which is not http, and we all have to read the new spec to implement things from scratch, then we will like those hidden complexities until the next cycle. now get off my lawn! -- sigh, and we need a genZ version of this, as we are not boomers to have lawns but i still want to highlight the generational gap :(