0

How do I determine the current CORS "state" in different browsers? I have for example a case where two different Access-Control-Allow-Origin headers are set, and I want to know which one applies now.

Usually I read through the specification in such cases, but I was unable to find this specific case. Additionally the specification does not always match the implementation right? How can I approach such a problem?

2 Answers 2

2

Your browser will not show the ACAO policy for the currently displayed page, because ACAO policies are request-specific rather than being tied to the current document. You can see the HTTP response headers sent by the server using developer tools, and the console should log any errors related to ACAO when you attempt to access a cross-origin resource.

Multiple ACAO headers are not legal. You should be seeing errors when you attempt to use them, no matter what browser you use.

Generally speaking, multiple headers of the same name are disallowed by the HTTP specification. A server response that breaks this rule should be invalid. However, this header uniqueness requirement is less strict in practice. A technique called "header folding" is permitted, in which the client may combine the values of two identically named response headers together into a comma-separated list. This was primarily introduced to support servers that returned multiple Set-Cookie headers. These days, this type of folding is generally still permitted in browser implementations, but servers are heavily discouraged from returning multiple headers because it can result in ambiguous behaviour.

You can see this in action when you try to use the Fetch API to request a cross-origin resource from a server that returns multiple ACAO headers. Here's the error you get in Chrome:

Access to fetch at http://otherdomain.foo/resource.txt from origin http://example.com has been blocked by CORS policy: The Access-Control-Allow-Origin header contains multiple values *, example.com, but only one is allowed. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to no-cors to fetch the resource with CORS disabled.

The server returned two Access-Control-Allow-Origin headers, one with * as a value and the second with example.com as a value. The browser folded these two values together into a comma-separated list, turning the effective value for the header into *, example.com.

However, this is not valid. ACAO does not support multiple origins:

<origin> Specifies an origin. Only a single origin can be specified. If the server supports clients from multiple origins, it must return the origin for the specific client making the request.

This is also why your browser's developer tools doesn't show you the ACAO policy anywhere other than in the HTTP response headers themselves. The only valid representation is a single HTTP header containing a single value, so there's nothing more to show you.

Ultimately, there are only two possible results of sending multiple ACAO headers:

  1. The browser rejects the response (or at least the header) outright because multiple headers of the same name were returned, and this is no longer strictly allowed by the HTTP specification; or
  2. The browser folds the two header values together into a comma-separated list, which Access-Control-Allow-Origin does not support, so the browser rejects it as invalid.

As a side-note, some HTTP header standards have included explicit guidance on how to handle header folding for a particular header, but these are rare (and often obsolete) and ACAO is not one of them.

0

The browser's handling of a CORS response is readily visible both via javascript (is the response body readable? are any other fields, such as headers that were supposedly exposed, visible?) and in the developer tools (insufficient CORS permissions, or other CORS violations, will cause errors in the console).

I could not find any requirement in the ACAO spec for what user agents should do in the face of multiple instances of the header, or a header with multiple values. In practice, multiple values don't work in any browser I'm aware of, but multiple headers (each with a distinct value) is probably unspecified behavior such that some browsers may accept the first one, last only, all of them, or none of them.

You can easily test what a given browser will do by setting up what should be a valid CORS request (and including a check for whether you can read the response) in a page's script, and then making a bunch of requests that return responses with varying ACAO: header patterns (different order, etc.). You can do this using server-side code (perhaps returning different header patterns for different endpoints), or using an intercepting proxy to modify the response headers individually.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .