-
Notifications
You must be signed in to change notification settings - Fork 539
CORS to respect the configured METHODS #2737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
@Stwissel can you have a look and let me know what you think? The spec is vague, should we block or should we make it configurable? |
@pmlopes can you point to the relevant section of the spec? Unfortunately in other sources, there is no mention of the status code https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors Btw, when this happens, shouldn't an |
The CORS spec is defined here: https://fetch.spec.whatwg.org/#http-cors-protocol The ambiguity is here: https://fetch.spec.whatwg.org/#http-responses
The issue that @Stwissel mentioned on discord is that in one hand we send a preflight that states we only allow GET, POST (as an example) but in fact if we don't have this check we don't block Cross Origin Requests for methods other than the configured ones... The Origin is explicit in the spec METHOD and HEADERS are ambiguous... Discord: https://discord.com/channels/751380286071242794/751397798271909941/1346839828745949244 Perhaps the idea of having this behavior behind a flag does make sense and allows us to keep the existing behavior by default? |
To complement the comment above, in MDN we can see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors/CORSMethodNotFound Browser behavior is expected to block requests if the preflight request includes a list of allowed methods. The issue here is that if I'd refer to the resource as an HTML image or iframe, e.g.:
Browsers will allow this (even though the image will be "broken" as it is, in fact, invoking a form endpoint). The assumption that your forms are "safe" falls in this case, as not all requests are controlled by a prefligh call by the browser. |
Thanks @pmlopes for all the details. I think it would be better to have a flag (enabled by default) that controls whether requests with invalid methods should be rejected. I'm still confused about the status code for rejection, because the CORS spec does not talk about it and MDN talks about 415, not 403. And I think in the response to the rejected request, we should add the list of allowed headers. |
We found servers playing fast and loose with origin headers, which in the current implementation fails, but typically a server sends data but without the cors headers. Maybe something like: CorsHandler corsHandler = CorsHandler.create()
.allowCredentials(true)
.allowedMethods(allowedMethods)
.addRelativeOrigins(new ArrayList<>(corsHosts))
.allowedHeaders(getAllowedCorsHeaders())
.exposedHeaders(getExposedCorsHeaders())
.failOnHostMismatch(false) // default is true, only applies to simple requests, not preflights
.maxAgeSeconds(7200); // 2 hours in seconds Small addition to the error message: the value of the origin header |
context
.fail(403, new VertxException("CORS Rejected - Invalid origin: "+origin, true)); |
The 403 comes from here:
I like the This should secure the simple requests (not pre-flight)
This approach would secure from web-based attacks (CSRF/XSS). No more images or iframes hacks to bypass the cors rules. Of course, if a request has no |
The 403 is fine, I'd just would like a way in the log to determine what origin failed. Good for trouble shooting and risk mitigation. Of course needs to be escaped if the origin is played back to the browser |
@pmlopes please ping me for another review when the PR is ready, and thanks again for looking into this! |
Motivation:
Currently the list of configured METHODs are only used to populate the preflight headers. This PR ensures that that requests are blocked
403
as per fetch spec: https://fetch.spec.whatwg.org/#http-cors-protocolOpen for discussion: