> I mean, it still relies on a vulnerable configuration (not checking the content type)
Unless I'm misunderstanding the claim, that's not "vulnerable configuration", but extreme lunacy - basically treating parsing outcome as access control. "Did the payload parse correctly as JSON? No -> go away; Yes -> oh that must mean you're supposed to be here". I'm at a loss of words that this is even a problem in practice.
> For adhoc dev tools
There's a whole space between "adhoc" and "dev" tools, though, and this is what interests me the most. Yes, when I'm in full dev mode, I can make my computer do anything I need to. But more often than that, I'm just a user that wants to exercise some basic freedom of computing - to remove some toil or frustration from daily computing experience - without switching my hat from "user" to "developer". That's what CORS has been successfully defeating, by forcing any ad-hoc non-dev tool I could make for myself to require being in "developer mode" to use it.
This is fundamentally a CSRF issue and framing CSRF as an access control issue often yields to wrong conclusions. With CSRF you might face the situation that the request has a valid session cookie, but is actually created by an attacker coercing the victim's browser into sending a request unbeknownst to the victim.
This case gets more and more complicated with browser defenses such as SameSite cookies or fetch headers you can use to mitigate this case, but let's ignore that for now.
To drive my point home, similar to how ensuring the content-type is set correctly on your JSON endpoint prevents CSRF, it's actually also a very real defense to require a custom header to be set, e.g.
Requiring this header will prevent CSRF because browsers won't allow you to set that cross-origin (unless of course you allow anyone to set it via CORS)Regarding the first part, it's easier than you might think to have a false sense of security.
I've seen a web application that did, in fact, check the Content-Type header to make sure that "application/json" was there - but it didn't check that the header value started with that. That meant that setting the header to "multipart/form-data; boundary=application/json" was enough to bypass a CORS preflight!