Skip to content

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

Open
@RubenVerborgh

Description

@RubenVerborgh

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions