6

The W3C CORS recommendation states:

Certain types of resources should not attempt to specify particular authorized origins, but instead either deny or allow all origins.

...

3. A GET response whose entity body happens to parse as ECMAScript can return an Access-Control-Allow-Origin header whose value is "*" provided there are no sensitive comments as it can be accessed cross-origin using an HTML script element. If needed, such resources can implement access control and CSRF protections as described above.

Does JSON parse as ECMAScript?

Can JSON produce side effects when executed via an HTML script element?

Can cross-origin web content gain read access to JSON GET responses from CSRF requests forged via an HTML script element?

What does "sensitive comments" mean in this context?

Does this paragraph apply to GET requests that do not accept cookies or HTTP Authentication for authorization? If a request were otherwise authorized only by OAuth for example, its response would not be accessible to a browser via an HTML script element. But by making its response include Access-Control-Allow-Origin: * for all authorized requests, the server would lose the ability to specify the origins to which the browser would grant access.

Wouldn't including Access-Control-Allow-Origin: * weaken the security of responses to requests authorized by cookies or HTTP Authentication? If a request were authorized by cookie, for example, it would be executable by the browser, but the source code in the response body would not be accessible to cross-origin web content. By making its response include Access-Control-Allow-Origin: *, the server would communicate to the browser that web content from all origins should have access to read the response in addition to executing it.

1 Answer 1

2

This much you understand already: The main idea here is that script elements (<script src="http://example.com/myscript.js">) are not subject to same-origin restrictions. Therefore, a site can load any script URL and execute that script (as long as the script does not require credentials or the browser has necessary credentials to access the script). However, the browser cannot read a script loaded in a <script> element.

You might rephrase the W3C's recommendation as:

If all the information in a resource can be obtained by running the resource as a script, then you may freely add Access-Control-Allow-Origin: *.

Therefore, raw JSON does not meet this requirement. If you execute the script:

(["foo", 5, 7])

then no information is added to the execution environment. (A few years ago, it could have, by redefining the Array constructor, but modern browsers have eliminated this vulnerability.)

However, the script

window.secrets = ["foo", 5, 7];

does make an observable change to the execution environment. You might as well allow the any page to fetch the contents of the resource through Ajax, because it contains no information that the page couldn't learn by running the script in a <script> element.

The phrase "sensitive comments" refers to actual JavaScript code comments (/* e.g., like this */). Comments are not readable from a <script> execution, but they would be readable when accessing the script content via Ajax. For example, the script:

// by the way, the fourth secret is "bar"
window.secrets = ["foo", 5, 7]

leaks the same information as the previous example when executed in a <script> tag, since the comment is only visible when viewing the actual script text.

If the resource requires OAuth credentials and does not accept cookie credentials, section 4 indicates:

requests ought to set the omit credentials flag and resources ought to perform authorization using security tokens explicitly provided in the content of the request

Cross-origin requests via HTML script elements would never include OAuth credentials, and those requests would fail authorization regardless of the value of the response's Access-Control-Allow-Origin header.

If the resource requires credentials and preflight, the preflight response it must also be served with Access-Control-Allow-Credentials: true. If the server doesn't send that header, then a site cannot send a cross-domain credentialed request to read the script content. Therefore, Access-Control-Allow-Origin: * does not weaken the security of the credential-protected resource, because credentials for the target domain will not be sent over Ajax unless the server also sets Access-Control-Allow-Credentials: true.

If the resource requires credentials but not preflight, the credentials would be sent in the request before the server has a chance to include Access-Control-Allow-Credentials: true in the response. The end result is the same -- the browser will not share the response with the cross-origin web content making the request -- but for different reasons.

Section 6.1 says:

The string "*" cannot be used for a resource that supports credentials.

And the resource sharing check would fall through step 2 of section 7.2 and fail at step 3:

  1. If the Access-Control-Allow-Origin header value is the "*" character and the omit credentials flag is set, return pass and terminate this algorithm.
  2. If the value of Access-Control-Allow-Origin is not a case-sensitive match for the value of the Origin header as defined by its specification, return fail and terminate this algorithm.
4
  • I suggested an edit to break down preflight and simple request scenarios. Commented Oct 17, 2013 at 3:24
  • Matt - your proposed edit changed too much of the answer
    – Rory Alsop
    Commented Oct 17, 2013 at 8:44
  • @MattMcClure I actually like your edit -- you've asked a very expansive question, and I could only answer most of it. Normally (if it weren't my own answer), I'd advise posting a new answer alongside this one, but in this case I'm happy to have your edits address the components of your question that I didn't answer. Even if you linked to this comment, though, it's still likely your edit would get unfortunately rejected; would you like me to edit in your changes myself, or would you like to take a second shot at it?
    – apsillers
    Commented Oct 17, 2013 at 11:55
  • @apsillers I think it would make the answer more complete if you could add my edits. Thanks for offering! Commented Oct 17, 2013 at 13:11

You must log in to answer this question.

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