-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
CORS, CORP, TAO & "public static resource" metadata #8143
Comments
/cc @annevk @mikewest @yoavweiss @domenic @eeeps |
I wonder about a version of (1) where we give Imagine something like:
The main delta I can see here is that there's no I apologize if this is a silly idea that has been discussed in the past. I suspect it has, perhaps back when CORS was originally being invented. In that case I'd be happy to accept a pointer those discussions and then we can continue discussing something more realistic like a document-wide CORS opt-in. |
My tendency is to support that when something is public it's exposed fully, otherwise we'll keep having to rule whether something is data or metadata, and that blurry distinction can lead to leaks . |
I really like @domenic's proposal, and think that would be the best outcome. If there are reasons against it, I'd appreciate pointers as well. /cc @arturjanc @nicjansma |
We've talked about this kind of thing in the past, and got hung up on complexities around reissuing requests without credentials if responses asserted Carving out the subset of requests that don't have any credentials might be a reasonable approach (though it's not enough to ensure that no cookies are sent, given client certs and etc.) I worry a bit that the story for developers would be complicated, and their sites would begin catastrophically failing if they accidentally sent a We've already started defining credentialess modes (https://developer.chrome.com/blog/coep-credentialless-origin-trial/). Perhaps that would be a reasonable thing to extend beyond its current applicability to CORPless responses? (/cc @ArthurSonzogni ) (Relatedly: I've had a bad idea floating around for a while that's relevant here: it would be ideal if we could somehow assert that a given server serves truly public resources, and won't ever have cookies and asserts CORS + TAO + CORP for all its resources. Origin policy was my initial shot at making such a thing possible, but maybe a smaller version would be to come up with a meaningful subdomain prefix (similar to |
CORP would still be able to override the "no Set-Cookie" restriction, right? Or are you concerned with sites that don't currently opt-into CORP, but would pass COEP restrictions with these new set of rules (unless a Set-Cookie sneaks in)?
Credentialless requests should definitely also be included in the set of rules we're discussing, and I can see a version of credentialless mode being the opt in discussed in (2). At the same time, (1) seems better from an adoption perspective, as it requires no extra work from developers. |
"catastrophicly failing" was hyperbolic, I grant you. :) My suggestion was simply that "anonymous CORS by default" would only work in those cases where no cookie had been set, and that setting a cookie would change requests' behavior in a way that I think would be confusing for developers (and difficult to recover from). |
I agree it would be confusing, but at the same time that may be offset by the adoption benefits and the fact that by default, no work would be needed on developers' behalf. /cc @philipwalton for opinions on the above tradeoff |
@mikewest I'm wondering if you may be trying to solve a more general problem than what is necessary for this particular use case. Specifically, given that -- at least in the context of TAO -- the benefits we're discussing apply only to loading cross-origin resources (most of the TAO-gated values are exposed same-origin by default), and that cross-site requests already don't carry cookies by default (and despite things like CHIPS and FPS it's likely that there will be fewer and fewer credentialed cross-site requests), the footgun potential might be fairly small? In particular, if Coming back to @domenic's proposal, I think one specific concern that came up in the past is that we need to consider that a request could be cached in response to a credentialed request and then returned from the cache when an uncredentialed request is made (see the note about But, overall, at a high level, |
I like that there's lots of traffic on this conversation but I'd love to hear thoughts from outside Google... @annevk? Someone from Mozilla? |
Thanks for bringing up this scenario! I vageuly remember @yutakahirano talking about making the cache CORS-mode aware. I think that would fix this particular issue. |
Possible tweak to domenic's proposal - I think I'd prefer something very explicitly, a long the lines |
Our implementation has separate buckets for credentialized and non-credentialized requests, does this address your concern? (@ArthurSonzogni made this.) Regarding the original proposal,
This includes both directions (e.g., |
I agree with @smaug----'s idea here. A brand-new header or a brand-new value for an old header would make sure it's an explicit opt-in. A new use for a value on an old header might cause problems for someone who was being sloppy about headers in a way that was harmless before now. |
Right
I don't think that's necessary. If "public static" behaves like "ACAO:* + TAO:*", then redirects should behave the same way they do today wrt to these headers, and if the redirect is also "public static" then it also implies having no credentials. |
(Some assorted thoughts and additional context.) The main reason CORS requires opt-in is credentials (cookies, HTTP authentication, and TLS client certificates). Those are included by default without CORS, and with CORS they are an option the requestor can set. (And yeah, an unfortunate problem here is caches. Some folks would support at least locally segmenting the cache, whereas others do not deem that a great solution due to the existence of intermediary caches.) And the main reason CORS has different requirements for I think the requirements around redirects will remain valid. The redirector might not be aware that the eventual resource is "public" and could therefore inadvertently reveal information. CORS enables read access. CORP enables read access by a Spectre attacker in current generation CPUs. TAO enables timing information. I've previously suggested TAO could be a subset of CORS, but some people had concerns about that. Given that CORS itself also has more detailed opt-in for various header metadata ( Having read this thread it's not entirely clear to me what we want here.
For the first 1 something along the lines of what @smaug---- suggested seems reasonable, provided redirects also opt-in. This has the danger of cargo culting as the server would no longer be required to echo the |
Thanks for the explanation, @annevk, I understand some of the context better.
I think CORS+TAO without requester opt-in would be one solution.
Yes, IMO the entire chain of redirects would have to opt in to being public.
Perhaps preventing cargo culting here is a matter of naming? |
We discussed this at TPAC in the WebAppSec session, including a bit during the break. Here's my attempt to summarize where I think we landed: There was a strong desire that the solution work (a) without requester opt-in; (b) on more than just cookieless destination origins. The most promising path forward in that regard is a new response header. This header is a promise that the resource is public and non-customized. It means that even though the request was sent with mode = "no-cors" / credentials mode = "include", the server is OK with exposing its data as if it were mode = "cors" / credentials mode = "omit". I.e., any origin can This approach has a footgun, which is that the server might be wrong. If the server applies this header to a response, but it actually does vary the response based on credentials, then the server has created a security hole. CORS attempts to prevent this footgun by requiring reflecting the The effects of this response header would be:
This header mainly affects the behavior of "no-cors" subresource fetches, and somewhat affects the behavior of "navigate" iframe fetches in terms of the metadata exposure. It barely effects "cors" requests (e.g. Things which were not discussed:
|
Another TBD from my perspective: whether this should also imply |
We continued the discussion over at webappsec and over a breakout session Summary:
|
I would appreciate someone briefly describing some scenarios this would enable. Because typically the requestor needs to know about CORS upfront (e.g., when wanting to read from And also what kind of changes to Fetch are envisioned as part of this. |
I will describe that when back from leave, alongside a draft patch to Fetch. |
A good example of a scenario this would enable at first is exposing meta-data that is traditionally CORS-protected without the need for CORS-negotiation - the server can opt out of this protection. Two examples:
I wanted to reach a consensus on the overall direction first, but my thoughts are that if the header is valid:
|
Alternate-ish proposal: To mitigate concerns about people over-allowing using this, another approach came to my mind instead of a new response header - a new request header that we send with This means that instead of the server saying "This resource is public", it says "I'm serving this resource to this particular requester, even though I don't know who it is" (which is essentially the same thing). Perhaps we can still add this to a new response header, as a way to include |
That sounds tricky/bad for caching. Not the kind of semantics you would want for something truly public. |
I thought about this further. I think the main and perhaps only use case for this is images. That's because:
So the only place where "CORSing all the things" is not feasible is images - mainly because of CSS ergonomics and the fact that images are both widely used and a very old feature. So instead of requiring developers to jump through hoops, I suggest we instead limit the scope (at least in the beginning) to images only. The header could look like:
We can also still include the following mitigations:
|
Strawman proposal for how this would work: whatwg/fetch#1617 |
Sorry, I haven't looked at that in a while. Just so that I follow, this is a response header right? |
Right. |
If we're so close to "just CORS" I'd rather figure out if we can get there somehow. Rather than introducing response-driven CORS just for images. E.g., by forcing CORS fetches to happen for a document or style sheet or some such. |
There is no viable "just CORS" proposal on the table ATM. If there was I'd be happy to discuss it... But I think a server-side solution that starts with images and perhaps expanded to video etc. is the most realistic. |
Well we have "require-corp". It wouldn't be out of the question to add a CORS-equivalent. |
This assumes that all the resources in the page would have to use CORS, and needs special semantics for anonymous/use-credentials. I think to do this properly we would need something like this (bikeshedding), but I'm not sure if it will get adopted:
|
@annevk how about something equivalent to referrer policies? |
I'd rather we avoid adding more mutable policies, especially for fetching. |
Understood. So I don't see how "CORSing all the things" would work. I'm afraid that all encompassing IMO it needs to be either a simple thing in the HTML, or something server-side at the embedded resource side (like proposed in #8143 (comment) |
After an internal conversation with @arturjanc and @yoavweiss, I would like to push forward a proposal that looks something like #8143 (comment). Strawman header: When a resource has this header, and the destination matches the request destination and a list of allowed destinations (currently only including 'image'), Fetch would treat the response as if it was fetched from the same-origin, for the purposes of CORP, CORS & TAO. |
Given that we recently introduced https://mimesniff.spec.whatwg.org/#minimize-a-supported-mime-type for Resource Timing to minimize passive information channels I'm even less convinced this is a good idea. At least forcing the requestor to set some kind of policy turns it into an active information channel. |
I appreciate the general concern around 3p origins passing each other information via a passive info channel. This should be a consideration when we introduce new channels, and we should still be careful when, for example, adding new attributes to resource timing. When introducing these channels, vendors can usually further restrict them for same-origin like WebKit does for server timing and In this case though, we're not introducing new channels. If a 3pA to 3pB side channel existed for CORS-same-origin images, it would be exposed today with using Can you elaborate on what kind of passive channel this adds? |
When |
I don't think we should use the fact we introduced that as an indication that there's consensus on the (undocumented) threat model that this is protecting against. I was supportive of that change to ResourceTiming as it didn't harm the actual use case, but that doesn't mean that I'd be similarly supportive in cases where there is a conflict between that threat model and useful functionality. |
I'm not claiming there is consensus though? Let's document it here as it's quite simple (I thought we did this before, but maybe not): Given a website A, embedding a cross-site image B and a cross-site (to both) script C, B shouldn't be able to broadcast all kinds of information for C to consume without the explicit cooperation from A. |
It's probably best to spin off this conversation to a separate issue, but it's not 100% clear to me how a |
Preliminary reading:
Notes on the threat model of cross-origin isolation,
w3c/resource-timing#220, w3c/resource-timing#240
Public static resources are resources that can be fetched by any user, and don't contain any user-specific data or metadata.
Images served by CDNs are a good example of such resources.
Today, to enable access to these resources by an embedder, the provider needs to:
This raises several issues:
The issue with CORS, is that it requires sprinkling
crossorigin
attributes all across the document, and apart from this ergonomic issue it is currently not supported for CSS images.CORP was originally meant as a feature for protecting against Spectre, and not as a carte blanche for exposing metadata about a resource. One of the reasonings for CORP in the first place was that the attack surface was limited (a Spectre attack is not trivial). Also, it's unclear where "embedability" and legibility stops and data access starts. CORP has amorphic boundaries when taken outside the Spectre-protection area.
TAO also has somewhat amorphic boundaries. e.g. when we add a new attribute to resource timing, how do we know that resources that opted in to TAO before are OK with exposing also this new attribute?
This is a complex situation, difficult to understand, and creates conflicts and doubts every time we propose a new feature that requires some cross-origin opt-in. For public static resources, this complexity seems unwarranted. As the web platform evolves, this might create a situation of "HTTP header per feature", where public static resources require a patchwork of HTTP headers to opt-out of privacy protection for resources that are not private in the first place.
I see two approaches to this problem (though there are probably more).
Allow public static resources to declare themselves as such
Basically extend CORP/ACAO or introduce a similar header to say: "I'm public. Always treat me as if I'm CORS."
This is very ergonomic, and I believe would make a lot of sense to web developers. However, it would become somewhat of a back door for replacing CORS, and there's a valid risk of misconfiguration.
Make "anonymous CORS by default" a viable & convenient option
If we want more sites to use CORS for everything, we need to make it possible and ergonomic. For example, a meta tag that declares that the default CORS mode for the document is CORS (strawman:
<meta name=crossorigin content=anonymous >
) and potentially a way to override it in CSS.Whatever direction we choose with this, I think reaching a consensus on this would be a very valuable outcome.
The text was updated successfully, but these errors were encountered: