- From: Jonas Sicking <jonas@sicking.cc>
- Date: Fri, 08 Feb 2008 01:52:17 -0800
- To: "WAF WG (public)" <public-appformats@w3.org>
Hi All, As I brought up in the call wednesday I have some ideas for simplifying the spec a bit. I think the syntax for the access-control header has gotten a little bit too complicated. There are two things that I think can be removed; the deny rule and the methods lists. Here's how: === The method lists === The method list is only useful for the OPTIONS request. This request is basically there in order to make sure that the server is aware of the existence of the AC spec, and that it is prepared to receive unsafe cross-site requests. But saying that you are prepared to receive requests is not the same as a promise to act on them. A server could simply state that it accepts any requests from any server, as long as it does the appropriate security checks once the actual request comes in. In fact, it's even recommended that the actual security checks be done in response to the request since otherwise there is a risk that a cached OPTIONS check will still allow requests to be sent for some time if security policies are ever changed (though never longer than the time specified in the Method-Check-Max-Age header of course). Additionally, the current syntax is inconsistent. When doing an OPTIONS request we send the requesting server's uri in the Referer-Root header. The reply (simplified) contains a set of uris. The set of uris is only used to check if the requesting site is part of the set, the rest of the set is ignored. This allows the server to do server side filtering and reply with "allow <*>". This does not mean that any other server is allowed to perform unsafe requests without doing an OPTIONS request first. In other words, we assume that sending a different Referer-Root could yield a completely different set of allow rules. This is not true for the set of methods. Here we do include the method in a Method-Check header, but we do remember the full set of methods that is included in the reply. I.e. we assume that sending a different Method-Check header would always yield exactly the same allow-rules. I propose that we remove both the Method-Check header, and the list of methods from the Access-Control header. This has several advantages: * It forces the security checks to happen at the time of the actual request which is what we should encourage anyway. * It makes the syntax a lot simpler and easy to understand. * It removes the inconsistencies. * It makes the implementation simpler. * And it means that sharing the Access-Control header for GET requests and OPTIONS requests makes more sense. This does assume that there is no methods that are so harmful that the server could not deal with cross-site requests of this type at all. I.e. they would cause harm before reaching the server side script. The spec would only allow all methods (reply with a set of allowed uris that includes the requesting one) or no methods at all (don't reply anything, or don't include the requesting uri in the set of allowed ones). I don't know of any such methods though. If that really is the case I would suggest we still don't include the Method-Check header, but instead add a separate response header that lists the set of allowed headers. However this would remove the first bullet in the list above which would be a pity. === The deny rule === Originally I think the deny rule came from me (not sure if this is true, not trying to take undue credit, rather trying to take the blame ;) ), and I think I had two reasons for this: 1. A way to allow server operators to quickly stop all cross-site requests without having to take down the whole site. 2. You would be able to put a sensitive resource on a server even if the server sent a allow<*> rule to all responses. You'd simply stick a <?access-control deny="*"?> PI in the resource. But I think there are better solutions to these problems. Thomas Roessler pointed out that 1 is better solved by simply stopping all requests that included a Referer-Root header. This could be done on a server level and would also stop any cached OPTIONS requests from making unsafe actions reach a CGI script. I like this idea a lot. The only problem is that I'm worried that the Referer-Root header might get picked up by other specs due to its usefulness and generic name. However if we specified that Referer-Root should only ever be included in cross-site request, then that should mitigate that problem. In fact, i've wanted to add a header for cross-site image and script loads to allow the server to reject these more easily. (That would of course not be part of this spec). I'm not really sure 2 is needed, nor would be used very often. You could simply not place the resource on the server if you know that it's sending allow<*> rules. And if you don't know that you are unlikely to put the PI in the resource at all. The main benefit of doing this is simplicity of the spec. However there is actually one more benefit. It would mean that making cross-site HEAD requests would be as safe as cross-site GET requests. The reason they aren't currently is that the response could include an allow <*> rule could include a deny-rule in a <?access-control?> PI. A HEAD request would only see the allow<*> header, but not the deny rule in the PI. This wouldn't really be a problem if there was no deny rules. It would mean that a resource that could be accessible using a GET request might not be accessible using a HEAD request though, but I think that is ok. And it's a lot better than a content author accidentally allowing HEAD requests to resources that could include access-control PIs if deny-rules exist. Something that I think could very well happen. / Jonas
Received on Friday, 8 February 2008 09:54:26 UTC