Repository navigation
Cross-Origin-Resource-Policy (was: From-Origin) #687
Description
Activity
Ping @whatwg/security.
Previous discussion #365
This might be OK to add as a stopgap, as long as we're clear that it doesn't actually solve the problem in general. We generally want a safe-by-default solution, not one that requires every single server to opt in...
Just to be clear - this is scoped to the response it occurs within, correct?
Yes. It is not stateful. The security benefit is that the browser can cancel the load and not bring the payload or meta data into the process where JavaScript is executed.
@johnwilander: Thanks, this does seem like a good fit for CORB, giving web sites a way to opt in to protection on arbitrary resources (not just HTML, XML, and JSON, though it would be a good failsafe for those as well).
@bzbarsky: I agree that both CORB and From-Origin only protect a subset of resources-- the largest we could come up with while preserving compatibility, plus anything sites choose to label with From-Origin. I agree with you that a secure-by-default solution would be preferable, but I'm not yet aware of one that can be easily deployed, at least in the short term. (For example, the idea of using credential-less requests for all subresource requests doesn't seem web compatible.) Happy to discuss options there.
I do think it's worth pursuing CORB and From-Origin at least as a stop-gap in the short term, since there's a fairly pressing need to get protection out there for as many resources as we can.
Let's discuss the subdomain aspect of this.
We'd like servers to be able to express that all pages from the same eTLD+1 are allowed to load the resource. The 2012 proposal as it stands requires the server to list all allowed domains which is error prone and uses up bytes on the wire.
Instead of having a resource on example.com send a response header like this:
From-Origin: cdn1.example.com, cd2.example.com, www.example.com, secure.example.com, example.com, many.sub.domains.of.example.com
... it could send something like this:
From-Origin: SamePrimary
... which would match example.com and any chain of subdomains of example.com. WebKit often refers to eTLD+1 as the partition.There are at least two pieces of prior art here, none of which seem to fit our needs:
- HSTS includeSubdomains which tells the browser to include subdomains of the current host in the policy.
- SameSite Cookies which imply that the hosts should match.
To further complicate things, eTLD+1 has many names:
- eTLD+1
- Partition
- Public Suffix+1
- Primary Domain
- High Level Domain
- Top Privately-Owned Domain
Some naming ideas:
From-Origin : SamePartitionFrom-Origin : SamePrimaryFrom-Origin : SamePrimaryDomainFrom-Origin : SameTPODFrom-Origin : SameETLD+1From-Origin : SameETLDPlus1From-Origin : SameETLDPlusOneFrom-Origin : SamePublicSuffixPlus1From-Origin : SamePublicSuffixPlusOne
Chrome and Firefox efforts seem to call that boundary "site", which is also reasonably understandable. So to add to your bikeshed, I'd argue for
From-Origin: same-site.The other thing we need to make concrete is for which responses this applies. Pretty much everything but top-level navigations? (For bonus points, would it apply to OSCP? See also #530.)
Something in this space seems like a good idea, so I'm supportive of the general direction.
I wonder, though, whether it would be simpler to build on existing primitives rather than add a new header. For example: what if we started sending an
Originheader with every request? Presumably, servers that would opt-into sending aFrom-Originheader would also be capable of blocking requests with unexpectedOriginheaders before passing the requests on to applications that might be damaged? (FWIW, I've also been toying around with the idea of sending a lower-granularityOriginheader as part of some future authentication primitive, which would boil down to an enum ofcross-site/same-site/same-origin).From-Originis potentially simpler to deploy for some endpoints that expect same-site usage, but always sending an indication of a request's provenance gives servers a lot of flexibility in how they deal with incoming requests. Since they're already dealing with that header for access control in general, relying upon it more broadly might be less overhead than creating a new primitive for the same purpose.To further complicate things, eTLD+1 has many names:
On this point in particular, I'd suggest that we'd be well-served to follow the PSL's "registered domain"/"registrable domain" terminology, or to follow the "site" terminology that
SameSitecookies defines, that Chrome's "Site Isolation" uses, etc. I don't believe the other terms listed above are as commonly used, but I'm happy to just agree on some spelling of the concept and putting it into a more easily-referencable document.Pretty sure Adam Barth tried
Originon each request to combat XSRF and it's simply not web compatible. That's why we ended up with the rules for it we have today.Pretty sure Adam Barth tried
Originon each request to combat XSRF and it's simply not web compatible. That's why we ended up with the rules for it we have today.If the objection is purely practical, perhaps @abarth could help us recall the challenges he ran into? I'd suggest that CORS is baked-into enough of the web at this point that it might be worth trying again (especially since I think there's at least tentative agreement from Firefox folks to expand
Origin's coverage to include some subset of non-GET/HEAD requests).I don't remember exactly, but I think the idea was to avoid request bloat. Adding bytes to every request is (or at least pre-HTTP/2.0 was) expensive, whereas scoping the extra bytes to POST made them negligible.
We've explored the idea of expanding
Originheader in the request as well but the challenge we face there is deployability. It's a lot easier for websites to deployFrom-Originheader on all resources than checkingOriginheader on every resource request while keeping it compatible with old browsers that don't send this request, etc...We've explored the idea of expanding
Originheader in the request as well but the challenge we face there is deployability. It's a lot easier for websites to deployFrom-Originheader on all resources than checkingOriginheader on every resource request while keeping it compatible with old browsers that don't send this request, etc...I think I agree that
From-Originis easier to deploy for servers, as it doesn't require much in the way of server-side logic. If we expand the scope of theOriginheader, servers would need to read it, process it, and do something useful with it, which certainly takes some effort. I'd suggest that expanding the scope ofOriginhas the additional benefit of giving servers the tools to more broadly mitigate CSRF attacks, but I'm willing to believe that fewer folks would be interested in doing the extra work. I think it's worth experimenting with that approach, but there's no reason we couldn't do both.I have a few detail questions:
-
@annevk suggested that this should apply to everything except top-level navigations. That misses auxiliary browsing contexts created via
window.open, which I imagine are same-process in some browsers. Would we want to address that vector as well? -
Does
From-Origin: SameSite(or however we end up spelling it), walk up the ancestor tree, or do we base the check purely on the initiating origin? We've recently fixedX-Frame-Options: SAMEORIGINto align withframe-ancestorsby checking the entire tree, and I'd suggest that that's the right behavior here as well. -
We apparently talked about this in CSP: Consider allowing
frame-ancestorsto work for subresource loads. w3c/webappsec-csp#17 as well. I'm less enthusiastic about adding new directives to CSP than I was in 2015, but it's worth evaluating whether we should consider this an analog toframe-ancestorsby adding a new CSP directive, or if we should add a new header entirely. -
Would we apply this to redirect responses, or just final responses? I vaguely recall differences in
X-Frame-Optionsbehavior on this point between browsers, so it's probably worth hammering out (FWIW, I'd suggest that we should apply the check to redirect responses, returning an error rather than following the redirect, as appropriate).
-
101 remaining items
Scheme checking for same-site
A no-cors HTTP resource loaded from an HTTPS context might remain popular and there are already ways to fix related security issues. It seems good to have CORP/same-site allowing it.
A no-cors HTTPS resource loaded from an HTTP context might not be as popular now and seems harmful, even in the long run. Maybe we can try disallowing this case.I agree with Youenn here. The scheme-matching case that worries me the most is http images on https pages. We know it is a common scenario and we're struggling with how to evolve mixed content blocking in the same regard.
The reverse doesn't worry me as much, i.e. requiring a scheme match for https resources on an http page if the https resource says same-site. The resource is clearly more secure than the page and so its policy response should protect it from ending up in a non-secure context. The only downside I see there is increased complexity, similar to how the referrer header gets stripped in http-to-https transitions. Developers have struggled to understand that for two decades. :/
- removedneeds concrete proposalMoving the issue forward requires someone to figure out a detailed planMoving the issue forward requires someone to figure out a detailed plan
on Jun 8, 2018 I was worried that might make it harder to transition to HTTPS, but since it's only same-origin/same-site that concern is likely overblown a bit. I'll write a test for that and update the standard PR accordingly.
I filed #760 on origin values.
- added a commit that references this issue
on Jun 8, 2018 Done, #687 (comment) is still in effect, except that there is now a scheme restriction in one direction. I'd appreciate review on the added text and the new tests.
Reacted by John WilanderI looked at the spec changes in #733 and they make sense to me. I also like @youennf's solution from #687 (comment) to not relax the
same-siterestrictions to HTTP origins when loading HTTPS resources (but allow loads in the other direction).LGTM overall for v1. I do think some developers may encounter problems during adoption due to the lack of origin-based granularity and not having sufficient visibility into who requests their resources, but this is likely something we can tackle in the future.
- added a commit that references this issue
on Jun 18, 2018 - added a commit that references this issue
on Jul 24, 2018 - added a commit that references this issue
on Jul 25, 2018 I tried to find bugs tracking implementation status in various browsers and this is what I came up with:
- Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=837379 (active)
- Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1459573 (active)
- Safari: https://bugs.webkit.org/show_bug.cgi?id=184560 (fixed)
I hope that the list above is useful going forward (I wasn't able to find links to these bugs in the comments above).
I also looked at https://master-dot-wptdashboard.appspot.com/results/fetch/cross-origin-resource-policy?label=master&label=stable&aligned and I see that Safari passes most WPT tests for CORP, but is not yet at 100%. I don't know how to see details of the test results or how to locally/manually run the tests against Safari - I am not sure what the failures mean (incomplete implementation in Safari? test issues?
are these tracked in a separate bug?).@anforowicz #733 (comment) has links, which include https://bugs.webkit.org/show_bug.cgi?id=186761 for Safari which was supposed to track remaining failures. Perhaps those are only in Safari Technology Preview? Or perhaps new tests landed since then.
cc @youennf
script-loads.html, image-loads.html and fetch-in-iframe.html are running fine locally and using w3c-test.org for me. I do not know why they are not showing up as such in WPT.
fetch.any.js seems to be buggy with regards to same-site.
It seems that fetch.any.serviceworker.html is run over HTTPS while fetch.any.html is run over HTTP on w3c-test.org, which has an impact on same-site behavior.I'll do a PR.
Reacted by Anne van KesterenUploaded web-platform-tests/wpt#14907
There are already extensions that e.g. disable X-Frame-Options; I worry that use of such would become
more widespread if CSP is seen as something that breaks the web - to no
security benefit for the user - by blocking third-party font and image loads.Only WPT failure seems to be related to case-insensitive comparison of the value. WebKit currently allows SAME-ORIGIN.
It does not seem that we have yet added tests for HTTP same origin loads from HTTPS contexts. We should probably be consistent no matter whether the load destination is Document or not.
I guess that we could either fail or return an empty response.
This seems to be a good topic to discuss in whatwg/fetch/github
Thanks
Security Advisor
@WPhH
Websites should have an explicit way to restrict any kind of cross-origin load to protect themselves against Spectre attacks. Content such as images, video, and audio may be sensitive and websites may be protected solely by virtue of their network position (inside a firewall), relying on the same-origin policy to protect against exfiltration.
There's a previous proposal from 2012 called the From-Origin header that we'd like to resurrect. With it, a server can send a
From-Origin : sameheader on responses it wants to protect from Spectre attacks. Here's a snippet from the currently inactive proposal:Cross-Origin Read Blocking (CORB) automatically protects against Spectre attacks that load cross-origin, cross-type HTML, XML, and JSON resources, and is based on the browser’s ability to distinguish resource types. We think CORB is a good idea. From-Origin would offer servers an opt-in protection beyond CORB.
In addition to the original proposal, we might want to offer servers a way to say cross-origin requests are OK within the same eTLD+1, e.g. the server may want to say that cross-origin subresources from cdn.example.com may be loaded from *.example.com without listing all those origins.