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.
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.
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.
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?
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.
The only reason this bug existed is because Rails treated HEAD as GET in some cases but not others. The sensible behavior here would be, in the Router, if the route didn't explicitly specify :head then it should convert the request to GET before handing it to the route. A route that wants to explicitly support HEAD (e.g. by skipping the response body) should explicitly specify :head on the route.
But the existence of this rails bug says nothing at all about the security of HEAD in general.
It is the main reason, yes, but not the only reason. If it wasn't possible to craft cross-site HEAD (which devs use in real life like.. never?) the bug would stop right there.
With an extra method if-else logic turned faulty. I would argue 90% web devs don't even remember of HEAD and what it means. Reasonably so, because it's rather never used.
IMO order of blame: 1) rails 2) browsers 3) github code relying on .get?
You're still focusing on the wrong thing. HEAD requests are largely obsolete at this point, yes, but that doesn't mean browsers would be right in changing the semantics of a HEAD request. The problem here isn't that browsers use the same security model for HEAD that they do for GET (as that's absolutely correctly) but that Rails decided to only partially support HEAD. Another simple fix for this bug would have been for Rails to simply give no special behavior to HEAD at all, and therefore any route that doesn't explicitly specify :head wouldn't be used for a HEAD request. The fact that Rails decided to deliver HEAD requests to a GET route without changing the request to actually appear as a GET request is a serious design mistake, and not one that browsers are responsible for.