Talk:Security/CSP/Spec
Is there an appropriate forum to discuss this?
We've been discussing CSP in lots of places, mainly in the mozilla.dev.security newsgroup. This is a great spot to discuss details of the CSP Spec, though. I've split this page into topics and am marking each issue as either open or closed depending on whether we have made decisions to resolve it or not. -Sid
Contents
- 1 User Script interaction (OPEN)
- 2 restrict TYPES for "object-src" (OPEN)
- 3 form-action Directive? (OPEN)
- 4 Version Beacon (CLOSED)
- 5 Script Languages (CLOSED)
- 6 X-Content-Security-Policy HTTP header (CLOSED)
- 7 Policy intersections (CLOSED)
- 8 javascript: URIs (CLOSED)
- 9 origin/host/source terminology (CLOSED)
- 10 What does 'self' represent? (CLOSED)
- 11 Scheme wildcards (CLOSED)
- 12 DNS wildcards (CLOSED)
- 13 Report XML mime type (CLOSED)
- 14 "Final" Directive to ignore META tags (CLOSED)
- 15 "font-src" and "xhr-src" directives (CLOSED)
- 16 Distinguishing Keywords (CLOSED)
- 17 Option (not source) Keywords (CLOSED)
- 18 frame-src Consistent Across Navigation (CLOSED)
- 19 video and audio src (CLOSED)
- 20 javascript: URIs by user (CLOSED)
User Script interaction (OPEN)
It seems like the spec should indicate how CSP interacts with user scripts (e.g. greasemonkey). --Sacolcor
Well, it should not affect them at all. Question is, is that technically possible? -- Gerv
restrict TYPES for "object-src" (OPEN)
Shouldn't "object-src" allow restrictions on what TYPES of objects are allowed, rather than just which hosts are allowed? -EricLaw
This sounds to me like over-complication. What's the use case? -- Gerv
I don't think its an over complication. The object-type directive could be optional. If it is specified then allow that type only, if its not present then all object types are allowed. On the flipside, if you argue for TYPE in objects, why not TYPE in images ? What is it about objects that demand a special object-type directive ?
A simple use case would be a enterprise app that has distributed a plugin to all its users to embed a proprietary format object. But for sake of security it doesn't want any flash or java in that page. --duryodhan
form-action Directive? (OPEN)
Should we add a form-action directive? Password theft can be accomplished if an attacker can inject an HTML form into a site. Password managers will even play along with this sometimes, even though the form action may target an attacker's site, and not self. -Sid
When you submit a form, thats a new web request, so isn't this already covered by the allow directive? In such a case, is there a use case for adding a specific form-src directive ? --duryodhan
Forms were not covered by the "allow" directive since there's user interaction required to submit the form; this is the same reason links to external sites aren't stopped by CSP. Any requests caused automatically by the page's load (dependent load requests) are subject to CSP, but if the user wishes to navigate away from the page, they're allowed. -Sid
Ok. Thats a very nice clear cut view -'anything without user interactions has CSP applied to it, without doesn't'. I am stupid and I didn't understand this from the spec - maybe you can add that somewhere appropriate ?
Additionally, in this scenario, while I do understand where you are coming from - there is a difference between links and forms. In links more often than not, you(user) know where you are going to. In forms unfortunately there is no indication in current UI of where the form data is going. So although there is user interaction in a form submission, whether user intent is there or not, is not clear. As such, I think forms should be covered by allow directive. If not, then a form-src also makes sense. --duryodhan
Assume form actions are subject to the allow directive as you recommend. If a site wants to allow form submissions to arbitrary third party sites (such as search boxes with arbitrary targets), then they have to open up the allow directive to be something like allow *. This is not safe, especially if the site authors don't want ActiveX controls or Scripts loaded from third party sites. As a result, the site authors have to then use the rest of the directives as blacklists instead of whitelists, making the policy a bit more confusing. If there's a form-action directive, then only one additional directive is needed aside from allow self to get a fairly closed-down policy that allows form submissions to arbitrary sites.
So either we need a directive to control form actions, or we shouldn't subject the form actions to CSP at all like anchor-based links (not even the allow directive).
Also, form-action is not part of the spec yet... but the more it is discussed, the more I'm starting to think it's useful. -Sid
I agree :). In addition, in the spec could you please clarify that the CSP is only applied to automatic HTTP requests and not those caused by User interaction (as I noted before)? I honestly thought that it applies to all HTTP requests.
--duryodhan
Version Beacon (CLOSED)
Is more misuse of the user-agent header the best way to go, or does handling a certain file type, a policy file, fall squarely in the realm of the Accept header?
I think using the UA field is appropriate. RFC 2616 shows that the UA header should specify "subproducts that form a significant part of the user agent". While CSP is not bulky, it is a major piece of how the user-agent can behave. Additionally, this approach will add five bytes to HTTP requests and will not require an additional header such as Accept-CSP. If there were an Accept-Policies or Accept-Security-Features header standardized, we would probably want to use that, but as of yet there are none appropriate at our disposal. -Sid
RFCs say a lot of things browsers don't actually do. It's hard to argue that CSP is a "subproduct" or counts as "significant" when entire content formats (SVG, MathML, XUL, XBL, video, ActiveX, plugins (they're products, significant, and not always there)) go unreported.
The alternative to the request announcing the support level is to version the reponse, and for the client to ignore policies with an unknown (newer) version. Combine that with server UA version sniffing if the server needs to decide which version of a policy to send. Or if we allow multiple CSP headers and intersect them (discussed elsewhere) then a server could simply send multiple versions which either get intersected into something sane in newer browsers or fall back to the older CSP header in older browsers. -dveditz
I perceive general distaste for version strings in the UA header, so I am going to modify the spec to be forward-compatible: (1) unknown directives are not fatal -- they are just ignored (2) future versions can implement directives with arbitrary values, but directives in the first version of CSP are restricted to their existing syntax.
Resolution: updated ABNF to allow future directives with arbitrary syntax. -Sid
Script Languages (CLOSED)
"No inline JavaScript will execute" should probably be generalized to "No inline script will execute" as there are a number of different script-protocol handlers in different browsers, and most browsers have the ability to host script other than JavaScript. -EricLaw
Good idea, updated accordingly. -Sid
X-Content-Security-Policy HTTP header (CLOSED)
Allowing the X-Content-Security-Policy header "anywhere" in the response clearly isn't correct-- it must be somewhere in the response *headers*. More importantly, it might be worth explicitly specifying that the header should/must appear in the initial headers and specifically not in TRAILER headers, because otherwise the entire page must be buffered to ensure that the policy is retrieved before the user interacts with the page. -EricLaw
Good idea, updated accordingly. We should probably remove the X- from the header name too, eventually. -Sid
Sid: that would require us to write and get published an RFC. :-) - Gerv
Gerv: One can dream. :) X-Content-Security-Policy it will remain for now. -Sid
Policy intersections (CLOSED)
I'd like to drop support for an HTML meta tag and instead support multiple headers. This brings up a question: how do we handle the multiple headers? There are two options:
- granular intersection -- Allow the HTTP subsystem to merge the two headers, separating each with a comma. Change CSP syntax to replace semicolons with commas. The result is a policy that can have multiple occurrences of each directive (including 'allow'), causing the CSP parser to intersect all multiply defined directives. For example, "allow *, script-src none, allow self" would be enforced as "allow self, script-src none".
- policy intersection -- Keep policies semicolon-separated and intersect multiple headers as the spec used to define intersecting the META policy with the HTTP header policy.
RFC 2616 says:
Multiple message-header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)]. It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma.
We probably want to do the "commas, no semicolon" option to prevent violating the RFC.
Please post thoughts on (1) dropping meta and (2) which of these two techniques to pursue. -Sid
I think we've agreed to drop meta, so I retitled this section. Technique 2 seems like the obvious one. -- Gerv
I've updated the spec to support intersection strategy 2 (comma-separated policies; semicolon-separated directives) and NO meta tag. I'm going to close this topic since I haven't heard any objections. -Sid
javascript: URIs (CLOSED)
Currently "JavaScript Uris" are restricted by both the "inline" and "eval" rules. This makes it unclear as to which I must allow to permit JavaScript URIs. -EricLaw
This is an unfortunate artifact of the late addition of the two opt-back-in keywords. It seems to me that javascript: URIs are probably "inline" code, but it's not completely clear. They could be considered "eval" code too (since it's code from string). I think maybe we should take the javascript: URIs out of the eval section. Thoughts? -Sid
Resolution: javascript: URIs are classified as 'inline'.
Reopening: Why not treat javascript: URIs as a hostless-scheme like data: disallowed unless specifically enumerated in one of the policies. -dveditz
Resolution (2): host-less schemes are supported in directives' source lists by stating the scheme name followed by a colon: javascript: and data: are examples. In fact, all schemes are supported this way, and any additional parameters on the source (host and port for example) are assumed to be "any" or *. -Sid
origin/host/source terminology (CLOSED)
Rather than using the term "host" and "source" would it be more accurate to replace all instances with "HTML5 Origin"? This term has a defined meaning and would remove ambiguity in cases (like report-uri) which are currently defined as both "same host" and "same source". -EricLaw
Alternatively, we could use Public Suffix + 1, like the domain indicator in the URL bar - a good compromise between the rigid "exactly the same host", which might be operationally inconvenient, or something so loose that you can leak info anywhere. -- Gerv
PublicSuffix+1 is a bad compromise. If we assume the author means exactly and only the host they specify then the policy is clear (no hidden meanings) and can be restrictive if necessary. If the author wants your behavior they can add a wildcard, which also has an explicitly clear meaning. -dveditz
Gerv and I were talking about different things. He was not talking about treating all origin/host/source directives as applying to an entire subdomain but rather specifically about allowing the reportURI (and policyURI?) be anywhere on the "same domain" rather than strictly "same origin". I'm ok with publicSuffix+1 for the reportURI but uncomfortable with going beyond same-origin for the policyURI. But having the two directives have different restrictions is confusing. I'm open to arguments that looser restrictions on the policyURI is OK (or that we don't need the policyURI at all -- it complicates a lot of things) -dveditz
Resolution: Requiring "same origin" for policyURI (scheme/host/port), and Public Suffix +1 for reportURI. --Sid
What does 'self' represent? (CLOSED)
"self" is defined as the scheme/host/port (origin) in the prose, but the flowchart defines it as document.domain. Which is it? -EricLaw
document.domain is evil, we should ignore it completely everywhere we can. -dveditz
"self" is scheme/host/port (origin). The flow chart is wrong and has been repaired. -Sid
On the same topic, do we want "self" to represent different things in different contexts or not? Should "http://self:80" be valid? Should "self:443" be valid? Should we only accept "self" alone with no scheme or port? -Sid
I really hate using self as a pseudo-host; either it's a keyword or it's not. "self" is same-origin with the page, otherwise it's easy to specify myhost.com:333 or ftp://myhost.com -dveditz
Would it be difficult to implement an intelligent "self" that was the same as the current URL for all unspecified bits? So it just Did The Right Thing? -- Gerv
Not difficult, but ambiguous, and it's not much more difficult to actually type the host name (it is available in the HTTP request).
Resolved: self will always represent (scheme, host, port) of the protected document.
--Sid
Scheme wildcards (CLOSED)
Do we want to support scheme wildcards, i.e., *://foo.com:80? My impression is no, but I want to be sure. -Sid
No-one's presented a use case. Let's call this one closed until someone does. Gerv
DNS wildcards (CLOSED)
The Host Expression List should describe exactly what types of wildcarding are permitted. For instance, can a * represent more than one DNS label? Can * appear in the middle or end of a string? -EricLaw
I'll clear this up in the spec, but the formal syntax should make the syntax explicit, but I will add discussion of the semantics of wildcard matching.
- One wildcard (*) per hostname is allowed
- Wildcard must be the leftmost hostname label (* and *.com are valid, www.*.com and mydomain.* are not)
- Wildcard represents any number of hostname labels (c.b.a and d.c.b.a both match *.b.a)
-Sid
Report XML mime type (CLOSED)
What MIME-type is used when sending the Report XML? -EricLaw
Any objections to application/xml? -- Gerv
Sounds good. -Sid
"Final" Directive to ignore META tags (CLOSED)
Should the HTTP header syntax allow a "Final" directive to force ignoring META tag declarations? -EricLaw
Closed as long as META is dead. -- Gerv
"font-src" and "xhr-src" directives (CLOSED)
Should there be a "font-src" restriction? -EricLaw
Good question. Right now fonts are subject to the "allow" catch-all directive, and loading third-party fonts requires loosening that restriction. Perhaps we should discuss adding such a directive as well as an xhr-source directive (for when cross-site xhr explodes). -Sid
I think we should do this, since fonts are a whole new beast. Marking this as closed; reopen if there's an objection. I'm also adding an XHR-src. -Sid
Distinguishing Keywords (CLOSED)
Should we distinguish keywords such as "inline", "self" etc. when they are in a hostname slot? I discussed possibilities with Sid, and we thought that single quotes might work well; script-src: 'self'. Other options are CAPS, or a $prefix %character. What do people think? -- Gerv
Using single quotes for 'none', 'inline', etc. -Sid
Option (not source) Keywords (CLOSED)
Should we move the keywords 'inline' and 'eval' out of the script-src directive? YES
Where should we put them?
- In the allow directive (allow self eval-script inline-script)
- In their own directive (allow self; options eval-script inline-script)
- As their own directives (allow self; eval-script; inline-script)
I'd prefer the "options" directive technique. Any thoughts? -Sid
I added an "options" directive to the spec. Feedback please! -Sid
Resolution: using the "options" directive. See the spec. --Sid
The frame-src restriction does not appear to take navigation into account. Suppose example.com has a refresh.php that serves a page with a Meta Refresh (e.g., like http://www.wizards.com/leaving.asp?url=http://www.adambarth.com/ but that proceeds automatically after a moment) and uses the following CSP policy:
X-Content-Security-Policy: allow self
Now, the attacker can subvert the frame-src policy by injecting the following HTML:
<iframe src="http://example.com/refresh.php?url=http://attacker.com/"></iframe>
The frame-src check will pass because the URL comes from example.com, but the frame will be loaded from attacker.com, circumventing the policy. We recommend that every change to a frame's src be validated against the frame-src whitelist. -- (reposted by Sid for abarth)
Not subjecting inner-frame navigation to the outer frame's CSP seems to force an inconsistent state, but doesn't seem fatal. Personally, I think it might be good to force the frame to eternally follow the CSP frame-src policy, but it doesn't feel like an urgent need to me.
-- Sid
What type of XSS attacks would 'eternally' follow protect against? --duryodhan
First example (a somewhat contrived example though) that comes to mind is the redirect example above, followed by a redirect back to a resource on example.com that has an XSS hole and no CSP set, perhaps because it's usually a top level page (http://example.com/failmessage.php?text=xss_outer_frame()). The inner frame is then same origin as the outer frame, but has some script reflected into it from the attacker's site. It can then access the outer frame and fool with it.
I dunno, like I said before, I'm not convinced eternal enforcement of frame-src is necessary, but this scenario might happen. -Sid
Yeah but if example.com has a flawed page and no CSP set, it can be hacked from another page also. The CSP enabled example.com's page would just end up saying that from this page you can't attack, which I don't think is worth is, because with an 'eternal' frame-src directive you are making life very hard for ads (think syndication). (afaik, imho) the attacks that happen with a malicious iframe are : the new redirect goes to a phishing page which looks like example.com and as the top URL bar also has example.com, the user is fooled into typing in his personal data. But this attack isn't XSS and shouldn't be handled by CSP I think. CSP should stick to protecting a web application from XSS --duryodhan
I agree CSP shouldn't address phishing, and we don't intend to do that. The situation I was trying to describe is the "hacked page" that ends up in a subframe of a sensitive page. The error page in the situation above, when victimized by XSS, may not be a huge risk -- when it's enframed by a more sensitive part of the site (say a page with account data displayed) the XSS can be used to extract more sensitive data.
-Sid
Once you XSS any page, can't you just XHR the a/c data page and get the data? Or you are saying that the A/C data page would have required the user to reenter his password ? I just think this case then becomes too contrived/obscure for CSP to take care off -- any such really sensitive page just shouldn't have a iframe from other page imho. --duryodhan
I'm going to close this. I'll try to make it more clear in the spec that this is the case with frame-src (it is not eternally enforced), but I think a happy compromise enforces the frame-src policy on HTTP redirects (30x) while missing refreshes/js redirects.
Resolution: Not changed. frame-src is enforced for HTTP redirects (30x). -Sid
video and audio src (CLOSED)
shouldn't there be a video-src and audio-src for the <video> and <audio> tags? Reasons for inclusion being the same as that for img-src. I am a little worried that there might be way too many <elementname>-src in the spec. --duryodhan
That's what media-src is intended for: video and audio. -Sid
I am an idiot. Sorry about that! But, Why is there a separate img-src ? Why isn't it covered in media-src ? (too many *-src tags still worries me :) --duryodhan
Embedded audio and video are relatively new compared to images on web pages and when rendered on a page these media are displayed with controls. Images by contrast can be backgrounds, and touch a completely different part of the code. In fact, it's completely reasonable to think that a site that wants to use images will want to prohibit videos from showing up -- especially since video codecs are newer and more prone to security-sensitive crash bugs than image codecs. -Sid
javascript: URIs by user (CLOSED)
If javascript: URIs are disabled by the site, and the user wants to execute some bookmarklet , it would still work ? I am pretty sure that the answer is yes, but just wanted to confirm. --duryodhan
See User Script Interaction. I think bookmarklets should fall under this umbrella, but not sure if they really do in implementations. -Sid
I am not sure either :). But I think as a spec, the document should think about these corner cases and clearly write out the expected behaviour. --duryodhan
Let me clarify -- I'm not sure if bookmarklets are deployed as user scripts or content scripts in various pieces of software (browsers). I haven't checked how different browsers behave. It is clear that user-provided scripts should not break (as per the CSP spec). I'm pretty sure "user provided" would include bookmarklets, since they're initiated by the user. I'll add the word "bookmarklets" to the spec to make this more explicit. -Sid