Skip to content

Cross-Origin-Resource-Policy (was: From-Origin) #687

Description

@johnwilander

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 : same header on responses it wants to protect from Spectre attacks. Here's a snippet from the currently inactive proposal:

The From-Origin header can be used to restrict embedding of a resource to only certain origins. When used it must match the following ABNF:

From-Origin = "From-Origin" ":" #(serialized-origin | "same")

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.

Activity

  1. johnwilander commented on Mar 28, 2018

    @johnwilander
    Author

    Ping @whatwg/security.

  2. jakearchibald commented on Mar 28, 2018

    @jakearchibald
    Collaborator

    Previous discussion #365

  3. bzbarsky commented on Mar 28, 2018

    @bzbarsky
  4. bzbarsky commented on Mar 28, 2018

    @bzbarsky

    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...

  5. mnot commented on Mar 30, 2018

    @mnot
    Member

    Just to be clear - this is scoped to the response it occurs within, correct?

  6. johnwilander commented on Mar 30, 2018

    @johnwilander
    Author

    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.

  7. csreis commented on Mar 30, 2018

    @csreis

    @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.

  8. johnwilander commented on Mar 30, 2018

    @johnwilander
    Author

    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:

    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 : SamePartition
    • From-Origin : SamePrimary
    • From-Origin : SamePrimaryDomain
    • From-Origin : SameTPOD
    • From-Origin : SameETLD+1
    • From-Origin : SameETLDPlus1
    • From-Origin : SameETLDPlusOne
    • From-Origin : SamePublicSuffixPlus1
    • From-Origin : SamePublicSuffixPlusOne
  9. annevk commented on Apr 3, 2018

    @annevk
    Member

    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.)

  10. mikewest commented on Apr 3, 2018

    @mikewest
    Member

    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 Origin header with every request? Presumably, servers that would opt-into sending a From-Origin header would also be capable of blocking requests with unexpected Origin headers 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-granularity Origin header as part of some future authentication primitive, which would boil down to an enum of cross-site/same-site/same-origin).

    From-Origin is 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 SameSite cookies 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.

  11. annevk commented on Apr 3, 2018

    @annevk
    Member

    Pretty sure Adam Barth tried Origin on 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.

  12. mikewest commented on Apr 3, 2018

    @mikewest
    Member

    Pretty sure Adam Barth tried Origin on 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).

  13. abarth commented on Apr 3, 2018

    @abarth

    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.

  14. rniwa commented on Apr 4, 2018

    @rniwa

    We've explored the idea of expanding Origin header in the request as well but the challenge we face there is deployability. It's a lot easier for websites to deploy From-Origin header on all resources than checking Origin header on every resource request while keeping it compatible with old browsers that don't send this request, etc...

  15. mikewest commented on Apr 4, 2018

    @mikewest
    Member

    We've explored the idea of expanding Origin header in the request as well but the challenge we face there is deployability. It's a lot easier for websites to deploy From-Origin header on all resources than checking Origin header on every resource request while keeping it compatible with old browsers that don't send this request, etc...

    I think I agree that From-Origin is easier to deploy for servers, as it doesn't require much in the way of server-side logic. If we expand the scope of the Origin header, 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 of Origin has 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:

    1. @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?

    2. 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 fixed X-Frame-Options: SAMEORIGIN to align with frame-ancestors by checking the entire tree, and I'd suggest that that's the right behavior here as well.

    3. We apparently talked about this in CSP: Consider allowing frame-ancestors to 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 to frame-ancestors by adding a new CSP directive, or if we should add a new header entirely.

    4. Would we apply this to redirect responses, or just final responses? I vaguely recall differences in X-Frame-Options behavior 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).

  16. 101 remaining items

  17. johnwilander commented on Jun 7, 2018

    @johnwilander
    Author

    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. :/

  18. removed
    needs concrete proposalMoving the issue forward requires someone to figure out a detailed plan
    on Jun 8, 2018
  19. annevk commented on Jun 8, 2018

    @annevk
    Member

    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.

  20. added a commit that references this issue on Jun 8, 2018
    ce08dff
  21. annevk commented on Jun 8, 2018

    @annevk
    Member

    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.

  22. arturjanc commented on Jun 15, 2018

    @arturjanc

    I 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-site restrictions 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.

  23. added a commit that references this issue on Jun 18, 2018
    0cec471
  24. anforowicz commented on Jan 15, 2019

    @anforowicz
    Contributor

    I tried to find bugs tracking implementation status in various browsers and this is what I came up with:

    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?).

  25. annevk commented on Jan 15, 2019

    @annevk
    Member

    @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

  26. youennf commented on Jan 15, 2019

    @youennf
    Contributor

    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.

  27. youennf commented on Jan 16, 2019

    @youennf
    Contributor
  28. larsonreever commented on Apr 5, 2019

    @larsonreever

    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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    addition/proposalNew features or enhancementssecurity/privacyThere are security or privacy implications

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions