Skip to content
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

Proposal: Allow servers to take full responsibility for cross-origin access protection #878

Open
RubenVerborgh opened this issue Mar 8, 2019 · 34 comments

Comments

@RubenVerborgh
Copy link

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

TL;DR: Servers that explicitly take full control of cross-origin access protection, do not want the browser to handle this. Unfortunately, fully and indefinitely opting out is currently impossible.

Following the WHATWG procedure for feature proposals, this issue describes the problem and use case requirements, not a solution (yet).

Problem description

By default, browsers are responsible for protecting cross-origin access to resources. This mechanism was created to avoid scripts running on one origin from having undesired access to personalized content on on another origin.

Currently, there is no sustainable way for a server to take full responsibility of cross-origin access protection. Servers can selectively opt out of blocking behavior, but no opt-out mechanism is guaranteed to work for all current and future applications. As an example, we recently witnessed breakage of several legitimate applications that relied on a widely used server-side configuration from enable-cors.org, because the fetch specification had changed in subtle ways. The only resort is reconfiguring all servers, without guarantee that this will be a permanent solution.

While useful as a default, the browser’s exclusive and changing control of cross-origin access creates an undesired obstacle in two common scenarios:

  1. when the server does not provide any personalization for a resource (“open data” or “public APIs”);

  2. when a resource’s personalized behavior is secured through other means such as API keys or authentication headers sent by the requesting script (“authenticated APIs”).

Use cases

(1) A Web server does not provide any personalization of certain resources, and wants to make those available to any Web application, now and forever.

Requirements:

  • The server must be able to indicate that it wants to take full control of cross-origin access protection
  • The server must be able to state this in a future-proof way
  • The server must be able to state this for specific resources
  • The server must be able to receive and send any headers, requests, and responses allowed by the HTTP specification, for those specific resources, from and to any origin
  • The server must be able to not positively respond to requests whenever it so prefers
  • The server must not require reconfiguration when the fetch specification is updated

(2) A Web server has its own cross-origin authorization mechanism for certain resources, and wants to make those available to any Web application, now and forever.

Requirements:

  • The server must be able to indicate that it wants to take full control of cross-origin access protection
  • The server must be able to state this in a future-proof way
  • The server must be able to state this for specific resources
  • The server must be able to receive and send any headers, requests, and responses allowed by the HTTP specification, for those specific resources, from and to any origin
  • The server must be able to not positively respond to requests whenever it so prefers
  • The server must not require reconfiguration when the fetch specification is updated

(3) A Web application that makes cross-origin requests to public resources on a certain server wants to keep working, now and forever (given no changes on the server).

Requirements:

  • The application must be able to set any headers on the request
  • The application must be able to read any response sent by the server
  • The application’s ability to do the above must not change over time

(4) A Web application that makes authenticated cross-origin requests to resources on a certain server wants to keep working, now and forever (given no changes on the server).

Requirements:

  • The application must be able to set any headers on the request
  • The application must be able to read any response sent by the server
  • The application’s ability to do the above must not change over time

(5) A browser wants to move the responsibility for granting access to cross-origin resources to the server, when requested.

Requirements:

  • The browser must be able to send a cross-origin request to the server unconditionally, when the server indicates that it takes full responsibility for cross-origin protection on that resource
  • The browser’s ability to do the above must not change over time

(6) A browser wants to maintain the possibility of providing granular cross-origin access protection to servers that do not explicitly opt out of this protection

Requirements:

  • Existing browser-based cross-origin protections must continue working
  • Existing granular CORS mechanisms must continue working

(7) A server developer wants a dedicated mechanism for taking server-side responsibility for cross-origin access control

Requirements:

  • The developer must understand what the mechanism does, and what responsibilities come with it
  • The developer must not rely on mechanisms that have a related, but more granular meaning
  • The developer must not abuse existing mechanisms to achieve this effect
  • The developer must be able to do this in a way that does not change over time

(8) A developer website (such as developer.mozilla.org) wants to document a future-proof way of taking server-side responsibility for cross-origin access protection.

Requirements:

  • These instructions must not change over time, or when the fetch specification is updated

Shortcomings of current mechanisms

Currently, when trying to address the above use cases, servers must resort to multiple HTTP header settings that eliminate cross-origin request blocking by enabling Cross-Origin Resource Sharing (CORS). In contrast, their actual goal is to request full responsibility for this protection. Therefore, the fact that only fine-grained settings are available is problematic, because:

  1. It is complex to indicate that a server requests responsibility for all current cross-origin requests, as this configuration involves an interplay of several HTTP headers with subtle edge cases.

  2. It is impossible to indicate that a server requests responsibility for all future cross-origin requests, because of continuing changes to the fetch specification that tighten the mechanism. As such, legitimate Web applications relying on CORS can break at any time.

Clearly, this complexity and progressive tightening are beneficial for the protection of the user and servers in general. However, this proposal argues that there are many common cases where the server explicitly wants to take that protection in its own hands: public data, open APIs, authenticated APIs.

Recent changes in the fetch specification broke widely deployed instructions on how to disable CORS. For instance, Web applications using HTTP requests with long headers suddenly stopped working in 2018/2019 after browser updates, even though their servers followed configuration instructions with the explicit intention of this not happening. Fixing those applications requires changes on the server side. Getting all affected Web servers updated is expensive and will likely take several years, and there is no guarantee that such an update will not be obsoleted again. It is unsure whether troubled servers will be updated in timely manner or at all, because blocked requests do not show up in server logs, so servers have no way of knowing that applications have trouble accessing their resources.

Note that we are not arguing against past or future changes to CORS. For security reasons, it is beneficial and necessary that the fetch spec keeps on updating. Rather, we are arguing for the existence of cases in which the server a) does not need that security because it it an open API, or b) is already taking the burden of security by authenticating cross-API requests in different ways.

We thus argue that a considerable number of servers emitting the Access-Control-Allow-Origin: * header actually aim to express their wish to take control of cross-origin request protection themselves, and thus for the browser to fully delegate that responsibility, instead of the much more nuanced and limited meaning this header actually has. These servers thus need a proper way of expressing this, without having to rely on the misinterpretation of an existing header.

Current Web applications

The following Web applications seemingly have the intention of requesting full server-side control of cross-origin access protection. Instead, they resort to workarounds which, as argued above, can break at any point (and, in multiple cases, are currently broken):

Authors of this proposal: Ruben Verborgh (@RubenVerborgh) and Pieter Colpaert (@pietercolpaert).

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

Is this a serious proposal for something new, or mostly just a complaint about CORS changing? (I'm not saying the complaint isn't valid)

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

This is a very serious proposal. We are working with public APIs, and recently saw applications break. We want a sustainable mechanism for the server to take control of cross-origin protection. (For insight into our serious intentions, see the discussions in #865 and #862; the above proposal is the result of several weeks of drafting and rewriting).

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

But the reason you don't see CORS as the solution is (1) multiple headers needed and (2) recent changes to CORS, or am I missing something?

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

As described in Shortcomings of current mechanisms above, the problem is 1) the complexity (which is broader than the need for multiple headers; also the fact some of those headers need to be reactive, which is harder to configure in NGINX/Apache), but mainly 2) that no such configuration is a final solution. We understand that the fetch spec is in evolution, as it should be, but this currently means that all public APIs and authenticated APIs have to keep on updating to be able to function like before. And since the solution is on the server side, Web apps have no control over breakage.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

I don't think any solution can be final. If you invent yet another opt-in, say Allow-Superpowers-And-I-Really-Mean-It: honestly, and 5 years later a new capability is released that would create a vulnerability on 5% of those opt-in sites, you then need yet another opt-in.

The CORS change seems bad, but I don't see yet another opt-in making things easier. Another opt-in has the same server-updating problem.

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

I don't think any solution can be final.

That would make stable public APIs and authenticated APIs an impossibility. I think we can do better.

If you invent yet another opt-in, say Allow-Superpowers-And-I-Really-Mean-It: honestly, and 5 years later a new capability is released that would create a vulnerability on 5% of those opt-in sites

The trick is in letting server operators understand exactly what they are opting in to. I challenge anyone to ask 10 server operators what they are opting in to when they are providing Access-Control-Allow-Origin: *. They will likely not know.

So this is not about opting in to certain features. It is a matter of saying Resource-Access-Protection-Responsibility: server or Resource-Personalization: none or Resource-Authentication-Responsibility: server. Providing a Web API that you want to be accessible from any Web app, regardless of what happens, seems like a very reasonable requirement.

The CORS change seems bad, but I don't see yet another opt-in making things easier. Another opt-in has the same server-updating problem.

So let's not have another opt-in then, but rather something sustainable.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

That would make stable public APIs and authenticated APIs an impossibility.

I don't think that's true.

So let's not have another opt-in then, but rather something sustainable.

What's your proposal, if not an opt-in?

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

That would make stable public APIs and authenticated APIs an impossibility.

I don't think that's true.

It is: dozens of Web APIs are running that have followed https://enable-cors.org/ with the intention of working from any Web application. These instructions no longer hold, so those APIs need an update on the HTTP level (= not stable). Furthermore, any such changes can happen in the future, so APIs will have to make adjustments (= not stable). Hence, I conclude that stable public APIs are not a possibility if servers do not have the ability to explicitly take responsibility for cross-origin access protection.

What's your proposal, if not an opt-in?

A mechanism by which a server can say "I am taking care of all current and future cross-origin protections for this resource", and/or "this is a non-personalized resource". So not a matter of opting in or out from specific features (which CORS is designed for, and still useful for), but rather deciding who assumes that responsibility. As such, servers accessed from the browser would have the same protections as when accessed from the command line or a native application. So apps can do nothing from the browser which they wouldn't be able to do through other means anyway.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

dozens of Web APIs are running that have followed https://enable-cors.org/ with the intention of working from any Web application. These instructions no longer hold

I don't know the history behind the CORS change. It seems pretty bad that a large breaking change was made. But, if that change was justified, similar future issues would be a problem for your proposal too.

What's your proposal, if not an opt-in?

A mechanism by which a server can say "I am taking care of all current and future cross-origin protections for this resource"

You're describing an opt-in.

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

But, if that change was justified, similar future issues would be a problem for your proposal too.

My proposal/request is exactly to be immune from such issues. Probably some security bug exists where long headers cause problem X or Y (@annevk couldn't publicly comment); hence the change. I'm describing a mechanism where the server says: you know what, if X or Y indeed are problems, then nothing additional is compromised compared to doing the same attack from the command line or a native app. Hence, I don't rely on the browser security mechanism. (This is very different from cases where, let's say, an API does cookie-based authentication, in which browser-based requests would have a privilege over other means.)

You're describing an opt-in.

Given that any mechanism could be characterized as opt-in (e.g., when I'm Accepting text/json, I'm opting in to JSON), I'll need better definitions to meaningfully address your concern with an opt-in. I do not share the view that opt-ins will necessarily need adjustments, if a server knows exactly what it is opting in or out of, and if that is broad enough to cover the above cases.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

My proposal/request is exactly to be immune from such issues

This guarantee cannot be made. If a vulnerability is discovered that puts real users at risk, browsers will fix that to protect users.

If the spec doesn't update, then the spec won't reflect reality.

If a browser doesn't update, users and competitors will rightly accuse that browser of being less secure than other browsers.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

Given that any mechanism could be characterized as opt-in

That isn't true. Only opt-ins can be characterised as opt-in. For instance, if you added this new behaviour by default, with a way for a server to say "I don't want this", then your proposal isn't opt-in (and an opt-out is provided).

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

For instance, if you added this new behaviour by default, with a way for a server to say "I don't want this" then your proposal isn't opt-in (and an opt-out is provided).

Indeed, what I am proposing is an opt-out. An opt-out of browser-side cross-origin protections (because the server takes care). I did not call it an opt-in.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

In/out doesn't matter. It's the 'opt' that's important. It's something the server has to opt for.

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

In/out doesn't matter.

I find it hard to argue this way. I am told that opt-in doesn’t work, that opt-out is not opt-in, I explain that it is opt-out, but then am being told the difference doesn’t matter.

So yes, the server opts for taking responsibility of cross-resource protection, just like it already has other responsibilities. What is the issue with that (given that servers are already trying to en masse)?

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

If the browser adds a new network capability, the responsibility of the server has changed without them being notified. If this results in a site's users being compromised, it's the browser's fault, because it was their change that broke things for users.

This is why we wouldn't introduce the new capability without an opt-in.

On one hand you say:

Getting all affected Web servers updated is expensive and will likely take several years, and there is no guarantee that such an update will not be obsoleted again. It is unsure whether troubled servers will be updated timely or at all

Then on the other:

The server needs to update.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

I find it hard to argue this way. I am told that opt-in doesn’t work, that opt-out is not opt-in, I explain that it is opt-out, but then am being told the difference doesn’t matter.

Where did I say "opt-out is not opt-in"?

@pietercolpaert

This comment has been minimized.

Copy link

@pietercolpaert pietercolpaert commented Mar 8, 2019

Today servers express a clear wish to opt-out through Access-Control-Allow-Origin: *. However, that is not what it strictly means. As evidenced by the recent small change, existing applications will keep breaking when opting out is not expressed in the specification. In the as-is situation, servers need to adapt their opting out walk-around as the spec evolves regardless of their use case.

Instead of having this walk-around servers now implement, we propose that a dedicated mechanism is put in place. This mechanism then becomes part of the living specification, where browser-vendors would be more cautious (never say never) to change anything on this part as it may break these applications.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

Let me try and explain:

If I said to you "Here is a button, if you press it, it gives me £20 of your money", nothing has changed by default other than the existence of the button. If you press it, I get £20 of your money, but it's fair to say you have opted in to this transaction.

If I just took £20 of your money, this was not an opt-in experience for you, because you were not consulted ahead of the transaction. It wasn't optional.

If I was going to take £20 of your money unless you pressed a button to prevent me, default behavior has still changed. You haven't opted in to giving me your money. You could say there's an opt-in feature to prevent me getting your money, but because the button reverts things to default, it's more commonly called an opt-out.

Similarly, you could frame CORS and your proposal as opt-ins or opt-outs, but they're definitely one of those, and they're both the same one.

If, for serious security reasons, breaking changes were made CORS, those same reasons would apply to your basically-the-same proposal. If a significant new capability arrived that required an opt-in, users of your proposal wouldn't bypass that opt-in unless it could be proven to be safe.

This is basically how CORS started. A new capability (cross-origin XHR) was introduced that was unsafe to enable by default, so an opt-in (CORS) was created.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

This mechanism then becomes part of the living specification, where browser-vendors would be more cautious (never say never) to change anything on this part as it may break these applications.

You're describing CORS.

@pietercolpaert

This comment has been minimized.

Copy link

@pietercolpaert pietercolpaert commented Mar 8, 2019

You're describing CORS.

We are indeed proposing additions to the fetch specification related to CORS to tackle the use cases that are not tackled today. See Shortcomings of current mechanisms and the uses cases described in our initial issue description ↑

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

I see the list of shortcomings, but nothing to show how the new thing avoids the same pitfalls (aside from the things already covered by https://github.com/WICG/origin-policy).

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

Where did I say "opt-out is not opt-in"?

That seems like a reasonable interpretation of

Only opt-ins can be characterised as opt-in.

then your proposal isn't opt-in (and an opt-out is provided).


Similarly, you could frame CORS and your proposal as opt-ins or opt-outs, but they're definitely one of those, and they're both the same one.

First of all, we are following the recommended the procedure at https://whatwg.org/faq#adding-new-features and thus proposing a problem that should be solved, not a solution. So "our proposal" (= a problem to be addressed) cannot be equal to "CORS" (= a solution). What we are saying is that the above use cases are not addressed by CORS, and we have received no indications of the contrary.

CORS is a method for relaxing very specific conditions of the cross-origin protection mechanism. CORS does not provide a method to complete opt out of cross-origin protection (if it does, please let us know).

At this stage, it seems highly preliminary to discuss potential solutions and their drawbacks, or to argue for the non-existence of any solution. We are currently looking for arguments that prove or disprove the validity, relevance, and importance of our use cases. Only when we have agreed that they are a problem that is not addressed currently, we should look into the possibility of creating and discussing solutions.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

@jakearchibald jakearchibald commented Mar 8, 2019

In terms of opt-out/in, I can only point back to the examples in #878 (comment).

It still sounds like a summary of the OP is "CORS behaviour shouldn't have changed".

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

It still sounds like a summary of the OP is "CORS behaviour shouldn't have changed".

That's not what I wrote at all; please don't misrepresent my use cases.

CORS can be changed in a thousand ways. I just don't want servers that explicitly do not want any cross-origin protections whatsoever, in whatever shape of form, to be affected by any such changes. Servers that do not explicitly opt out of such protections, or who only granularly opt in to CORS using the existing mechanisms, will and should be affected by all the changes.

So if anything, I'm advocating for a "do not bother me with CORS protection" switch, precisely because CORS will and needs to keep on changing in the future. Very different from "CORS behaviour shouldn't have changed".


Update: although I do not see how the original text could be interpreted as "you shouldn't have changed CORS", I nonetheless added an explicit section which explains that CORS changes are good and necessary. So let it be clear that we are advocates for secure CORS.

@sleevi

This comment has been minimized.

Copy link

@sleevi sleevi commented Mar 8, 2019

@jakearchibald I think it's fair to say that there are two points - one which is a suggestion that existing functionality should not have changed, and another suggesting there should be a guarantee not only that existing functionality won't change, but that servers won't need to change to take advantage of new platform features (or relax any newly tightened restrictions on existing features)

I think both could have some parallels drawn to the discussion between Mixed Content. Historically, UAs were very lax in their permissiveness of both active and passive mixed content. Developers were allowed to choose what they felt was the appropriate trade-off between security/privacy and functionality, and thus would very often load HTTP content into the context of HTTPS, exchange cookies around between the two, etc.

The desire is reasonable, but I think it runs into challenges when faced with the Priority of Constituencies and Secure by Design

The former prevents being able to guarantee that nothing will ever change - as UAs need to ensure that the User's needs and wishes are first and foremost respected - while the latter means that new features need to consciously consider whether there are risks to introducing them, and if so, ensure that they are introduced in a way that can safely reasoned about.

The problem with a default opt-out is that it cannot be safely reasoned about, because at the time the opt-out was made, the information wasn't available. There's no way the developer could have made a (truly) informed choice, and it seems that some of the discussion of the problem is really a difference in philosophy about whether or not the developer was making an informed choice.

The problem with guaranteeing there won't be behaviour changes is that, as you highlighted, our understanding of the Web Platform and its security evolves over time, as do the needs of the users, and so that the Web evolves around those. This is fundamentally reflected in the nature of this spec being a Living Standard - things change.

Independent of exploring solutions, it may be that there is a fundamental disagreement on the nature and validity of the problem, and whether or not web developers or user agents should be the arbiters of user security, both presently and in the future. This is an inherent tension UAs face - users want and benefit from powerful new functionality and features that enable otherwise inaccessible use cases, but users also want privacy and security and safety when interacting with the Web Platform.

@RubenVerborgh Do you feel that I've accurately captured some of the tension in perspective?

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

@RubenVerborgh Do you feel that I've accurately captured some of the tension in perspective?

Unfortunately not.

there are two points - one which is a suggestion that existing functionality should not have changed

I did not make that point and I do not agree with that point.
So for the sake of argument, I will explicitly state it here:

It is good that CORS has changed. It protects those servers that only wanted to selectively disable some cross-origin protections, which is what the CORS headers provide.

another suggesting there should be a guarantee not only that existing functionality won't change

I did not make that point and I do not agree with that point.
So for the sake of argument, I will explicitly state it here:

I think CORS functionality should keep on changing to protect those servers that only want to selectively disable some cross-origin protections.

The problem with a default opt-out is that it cannot be safely reasoned about

I am not arguing for a default.

because at the time the opt-out was made, the information wasn't available. There's no way the developer could have made a (truly) informed choice

Why not?

If I know that my resources are public and not personalized, what is not informed about my choice to say, I will take indefinite responsibility for cross-origin requests for these specific resources?

@sleevi

This comment has been minimized.

Copy link

@sleevi sleevi commented Mar 8, 2019

@RubenVerborgh Apologies for misunderstanding your point, then.

To make sure I'm accurately understanding your point and accurately presenting it:

  • I think the point about 'default opt-out' was moreso that a given 'nu-opt-out' will, by default, also opt-out of any new changes. I believe that's consistent with the proposal, but I want to make sure. It seemed that there was some concern that there was an expectation that the current opt-out would provide that level of functionality (hence the discussion of https://enable-cors.org), but it didn't.

Is that better?

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 8, 2019

Thanks for trying to summarize @sleevi, that's helpful.

'default opt-out' was moreso that a given 'nu-opt-out' will, by default, also opt-out of any new changes

Fair enough. If a server says, "I don't want feature X", then it is indeed also opting out of all future alterations to X. Just like, as a server, when I don't provide content negotiation, I am also opting out of content negotiation changes in the future. That is indeed very much the point.

It seemed that there was some concern that there was an expectation that the current opt-out would provide that level of functionality

I will remove the mentions out of enable-cors from point 8, they can indeed be confusing.

@dbaron

This comment has been minimized.

Copy link
Member

@dbaron dbaron commented Mar 9, 2019

A number of your use cases (2, 4, and 7) refer to authentication or access control. I think understanding whether those use cases are being addressed securely (and, e.g., not in a way that's subject to the confused deputy problem) requires understanding what the use cases for that authentication or access control are. That is, why is authentication or access control being used, and is this solution sufficient for that reason?


Also, one other side comment: while Access-Control-Allow-Origin: * may or may not be the best name for what it does, its design serves a very important use case, as Anne has pointed out in a number of other discussions: it tells the browser that the data can be shared in any way that is known to be safe if the server is on the public internet (rather than behind a firewall). This means that this header is designed so that it can be safely added to the HTTP responses on all servers that aren't behind a firewall, and thus can make large amounts of data usable cross-origin in browsers, quickly, without introducing a bunch of security risks that require careful thought.

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 9, 2019

A number of your use cases (2, 4, and 7) refer to authentication or access control. I think understanding whether those use cases are being addressed securely (and, e.g., not in a way that's subject to the confused deputy problem) requires understanding what the use cases for that authentication or access control are.

Thanks @dbaron, that's a very relevant point indeed.

So, broadly (and very loosely) speaking, I see four categories of authentication between browser apps and a server:

  1. none (public resources)
  2. based on network access (e.g., IP or firewall, as mentioned in the fetch spec)
  3. based on one client-side secret for all origins (e.g., cookie)
  4. based on a per-origin client-side secret (e.g., OIDC)

Clearly, cross-origin protection is necessary for the second category, or the danger is that a web app reads privileged information. It is also necessary for the third category, if the client uses credentials: include, for the same reason. In both categories, the protection prevents that a script on evil.com can send a request to good.com and obtain personalized information.

The problem is that the browser doesn't know in which of the categories it is, so it makes a pessimistic assumption (for instance, that it is in category 2). That makes sense, given no explicit indication of which category it is in.

However, cross-origin protection is also applied in categories 1 and 4, and undesirably so, if the browser is told by the server in which category it is.

In category 1, the resource is public. So anyone from anywhere in the world sees the same thing; as such, the user's information cannot be compromised. So if the server were to state "this is a public resource", then not having cross-origin protection (now or in the future) is perfectly acceptable.

In category 4, evil.com cannot access the resource unless the user has authorized evil.com, in which case an evil.com-specific key will be sent to the server. So again, no need for browser-side cross-origin protection here if the server indicates that it is taking care of cross-origin protections, because another mechanism is active that handles these protections.

We do not have a confused deputy problem in these categories. In 1, anyone can access. In 4, access for the specific origin is regulated through another mechanism.

That is, why is authentication or access control being used, and is this solution sufficient for that reason?

Given that, as proposed, the server explicitly indicates that it takes control of cross-origin protections, then:

In category 1, no authentication is used/needed at all (so sufficient).
In category 4, authentication is used to personalize (access to) resources, and this personalization is regulated through another mechanism (so sufficient).

This means that this header […] can make large amounts of data usable cross-origin in browsers, quickly

Well, yes and no. Yes, in that several cases work; no, in that it has become difficult to provide an exhaustive list of conditions that requests have to satisfy before being usable—or, conversely, an algorithm to generate the necessary headers for any request to be usable. And any such a list or algorithm would not be stable.

Understood that such changes happen for security reasons, but the above categories 1 (no auth) and 4 (separate auth) are not impacted by them if the server chooses to regulate cross-origin protection itself. So that's why I am arguing for a sustainable solution for those categories.

(Note: categories 1 and 4 correspond to scenarios 1 and 2 in the section “Problem description”.)

@annevk

This comment has been minimized.

Copy link
Member

@annevk annevk commented Mar 11, 2019

I could see a TLS-level assertion that the server is basically open to all kinds of connections/requests and is able to protect itself as a thing that might be workable: quicwg/base-drafts#1993. There's a lot of risks for the server involved though as I outlined in a comment there.

For CORS itself it seems worthwhile to wait on how Origin Policy/Manifest works out.

@RubenVerborgh

This comment has been minimized.

Copy link
Author

@RubenVerborgh RubenVerborgh commented Mar 11, 2019

I could see a TLS-level assertion that the server is basically open to all kinds of connections/requests and is able to protect itself as a thing that might be workable: quicwg/base-drafts#1993.

That is a very interesting direction indeed; opens up some possibilities.

For CORS itself it seems worthwhile to wait on how Origin Policy/Manifest works out.

Origin Policy is definitely another interesting direction. However, currently, the Bypass mode still seems very restricted (https://wicg.github.io/origin-policy/#fetch-bypass-preflight), so might not address the above use cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
6 participants
You can’t perform that action at this time.