Block all non sri resources #64

Closed
wants to merge 4 commits into
from

Projects

None yet

9 participants

@oreoshake

Discussed here: https://lists.w3.org/Archives/Public/public-webappsec/2015Dec/0045.html

@mikewest I really have no idea what I'm doing here. In particular, the algorithms section was just sorta slapped together.

/cc @ptoomey3

oreoshake added some commits Mar 17, 2016
@oreoshake oreoshake Add initial spec text for 'block-non-sri-resources' 83a4512
@oreoshake oreoshake add 'document' references in makefile 48e6f36
@oreoshake oreoshake remove todo d972f5c
@oreoshake oreoshake update generated html
ce2ead9
@ptoomey3 ptoomey3 commented on the diff Mar 17, 2016
document/index.src.html
4. If |policy|'s <a for="policy">disposition</a> is "`enforce`",
return "`Blocked`".
2. Return "`Allowed`".
+ <h4 id="directive-block-non-sri-resources">`block-non-sri-resources`</h4>
+
+ The <dfn>block-non-sri-resources</dfn> restricts loading resources that do not
+ contain an integrity attribute specified by [[SRI]]. The syntax for the
+ directive's name and value is described by the following ABNF:
+
+ <pre>
+ directive-name = "block-non-sri-resources"
+ directive-value = "" / token *( RWS token )
@ptoomey3
ptoomey3 Mar 17, 2016

I'm not familiar with the syntax here, so does the * imply an "all" wildcard? If not, it should probably be added.

@shekyan
shekyan Mar 17, 2016 Contributor

this should looks something like

directive-name = "block-non-sri-resources"
directive-value = sri-token

sri-token = "'script'" / "'style'" / "*"
@mikewest
mikewest Mar 18, 2016 Member

I don't think the grammar should be that strict. I'd prefer to see something generic in the grammar, and a note that unrecognized tokens should be ignored so that we can add new types in the future when SRI advances. That is, link token to https://tools.ietf.org/html/rfc7230#section-3.2.6, RWS to https://tools.ietf.org/html/rfc7230#appendix-B, and define directive-value as [ token *( RWS token ) ]. You'd then need to define how to match the various tokens in algorithms below.

Note: The link between the types in this list and the behavors that SRI defines is actually a good reason to move this directive to SRI rather than tying it to this document's status.

@michaelficarra
michaelficarra Mar 20, 2016 Contributor

I disagree. Implementations already ignore a directive if they cannot recognise it. The grammar suggested by @shekyan is more clear.

@mikewest
mikewest Mar 20, 2016 Member

I agree that implementations ignore unknown directives, and I agree that it's a good thing. I'd suggest that that means that we ought to ignore unknown tokens in a directive's value as well, which is what I'm suggesting.

@michaelficarra
michaelficarra Mar 20, 2016 Contributor

I don't know if that's a good thing. Allowing an implementation to accept a malformed directive can lead to some negative security consequences. That is why, in Salvation, we either parse an entire directive successfully or we drop it with a warning. We will never make an assumption about the meaning of a malformed directive because an attacker can take advantage of that assumption.

@mikewest
mikewest Mar 20, 2016 Member

Among other things, that would have meant that we couldn't add nonces or hashes to script-src, as they weren't known tokens in CSP1. Given that we don't really know what we want from this directive, ignoring unknown values with an eye towards forward compatibility seems reasonable.

@shekyan
shekyan Mar 21, 2016 Contributor

Regardless if it's going to be implemented as rfc7230 token or a specification defined grammar, I realized that there is no place for U+002A ASTERISK character (*). Wildcard in other contexts of CSP represents most permissive value, while for this directive it would mean most restrictive, which can be a big source of confusion for developers.

@fmarier
fmarier Mar 22, 2016 Member

sri-token = "'script'" / "'style'" / "*"

I'm not sure * makes sense here. I understand the desire to turn on all sri checks at once, but I can imagine the following scenario that would not be forward-compatible:

  1. Webdev adds require-sri-for * to CSP and annotates scripts and styles.
  2. Firefox only supports SRI for scripts and styles so it only checks that.
  3. (time passes, webdev forgets about CSP)
  4. Firefox adds support for SRI in img elements.
  5. Site breaks because Firefox refuses to load non-sri images.

If we force developers to be explicit about what they require then when browsers start adding sri support to new elements, developers will have to add the attributes and then update their CSP once they've done that.

@ptoomey3
ptoomey3 Mar 22, 2016

Isn't the same true for something like default-src 'none' if/when other new directives are subject to default-src? We had been paranoid about this and specified an explicit policy for every directive we knew about and set a default-source * to avoid potential breakage. We only recently gave up on the paranoia and switched it to 'none', assuming we will catch any breakage from following the csp spec and reports from preview release users on chrome/Firefox.

@oreoshake
oreoshake Mar 22, 2016

We want to explicitly avoid * value for forward compatibility. The * I originally added was to denote "any number of tokens".

EDIT: I chatted with @ptoomey3 and I've come around to his thinking.

@mikewest
Member

Thanks, this is a good start! But it needs a lot more work. :) Will add comments inline.

@mikewest mikewest commented on the diff Mar 18, 2016
document/index.src.html
4. If |policy|'s <a for="policy">disposition</a> is "`enforce`",
return "`Blocked`".
2. Return "`Allowed`".
+ <h4 id="directive-block-non-sri-resources">`block-non-sri-resources`</h4>
@mikewest
mikewest Mar 18, 2016 Member

Bikeshed: I'd prefer something non-double-negative. require-sri-for might work, for instance. I'm open to whatever, but "block things that aren't X unless they're not in the following list" gets hard to parse.

@mikewest mikewest commented on the diff Mar 18, 2016
document/index.src.html
+ The directive recognizes a number of potential token values:
+
+ * `script` requires SRI for scripts
+ * `style` requires SRI for style sheets
+
+ <h5 id="sandbox-algorithms">Algorithms</h5>
+
+ This directive's <a for="directive">response check</a> is as follows:
+
+ Given a <a>request</a> (|request|), a <a>response</a> (|response|), and a
+ <a>policy</a> (|policy|):
+
+ 1. For each resource in document:
+
+ 1. If the resource's type aligns with the token values and that resource
+ type is contained in the directive, return "`Blocked`".
@mikewest
mikewest Mar 18, 2016 Member

type aligns with the token values

This needs to be specified a little more tightly, probably along the same lines as https://w3c.github.io/webappsec-csp/#effective-directive-for-a-request (maybe making use of that algorithm directly to map a Fetch Directive name to one of the tokens you define above?).

@mikewest mikewest commented on the diff Mar 18, 2016
document/index.src.html
+ directive-value = "" / token *( RWS token )
+ </pre>
+
+ The directive recognizes a number of potential token values:
+
+ * `script` requires SRI for scripts
+ * `style` requires SRI for style sheets
+
+ <h5 id="sandbox-algorithms">Algorithms</h5>
+
+ This directive's <a for="directive">response check</a> is as follows:
+
+ Given a <a>request</a> (|request|), a <a>response</a> (|response|), and a
+ <a>policy</a> (|policy|):
+
+ 1. For each resource in document:
@mikewest
mikewest Mar 18, 2016 Member

This check is executed at the bottom of a resource fetch; there's no "document" that you can directly grab, nor do I think you need to grab a document, as you should have all the data you need in the |response|.

@mikewest mikewest commented on the diff Mar 18, 2016
document/index.src.html
+ contain an integrity attribute specified by [[SRI]]. The syntax for the
+ directive's name and value is described by the following ABNF:
+
+ <pre>
+ directive-name = "block-non-sri-resources"
+ directive-value = "" / token *( RWS token )
+ </pre>
+
+ The directive recognizes a number of potential token values:
+
+ * `script` requires SRI for scripts
+ * `style` requires SRI for style sheets
+
+ <h5 id="sandbox-algorithms">Algorithms</h5>
+
+ This directive's <a for="directive">response check</a> is as follows:
@mikewest
mikewest Mar 18, 2016 Member

I think you can do a little better than this by defining a "pre-request" check for the directive that examines the Request and compares it to the token list. Something like:


Given a request (|request|) and a policy (|policy|):

  1. If |request|'s type [insert some sort of matching algorithm here, as discussed below], and |request|'s integrity metadata is the empty string, return "Blocked":
  2. Return "Allowed".

You'll probably need to work with @metromoxie, @mozfreddyb, @fmarier, @devd, and @annevk to wire up HTML's fetching mechanisms for <script> and <style> (and whatever comes next) to Fetch (basically, start by moving everything from section 3.6 and section 3.8 to HTML. But once that infrastructure is done, the check here should be pretty straightforward.

@metromoxie
metromoxie Mar 22, 2016 Contributor

It seems to me like this could be greatly simplified just by modifying Fetch with something like:


In 5.1 "Main Fetch", add the following step after step 5:
If "should block fetch due to lack of integrity metadata" returns blocked, set response to a network error.


Then, you can define in the CSP spec the "should block fetch due to lack of integrity metadata" similar to what @mikewest described above.

@mikewest
mikewest Mar 22, 2016 Member

I don't think we need a new algorithm for that; hooking into the "pre-request" check would wire this directive up to the existing CSP hook in step 5 of Main Fetch. I'd prefer to keep that simple integration rather than adding a new step to Fetch for every feature that influences fetching.

@metromoxie
metromoxie Mar 22, 2016 Contributor

Ah, you're absolutely right. I was misreading Step 5. My apologies. In summary: I completely concur with @mikewest's suggested structure ;-)

@mikewest mikewest commented on the diff Mar 18, 2016
document/index.src.html
4. If |policy|'s <a for="policy">disposition</a> is "`enforce`",
return "`Blocked`".
2. Return "`Allowed`".
+ <h4 id="directive-block-non-sri-resources">`block-non-sri-resources`</h4>
+
+ The <dfn>block-non-sri-resources</dfn> restricts loading resources that do not
+ contain an integrity attribute specified by [[SRI]]. The syntax for the
+ directive's name and value is described by the following ABNF:
+
+ <pre>
+ directive-name = "block-non-sri-resources"
+ directive-value = "" / token *( RWS token )
+ </pre>
+
+ The directive recognizes a number of potential token values:
+
+ * `script` requires SRI for scripts
+ * `style` requires SRI for style sheets
@mikewest
mikewest Mar 18, 2016 Member

The parsing here needs a little more work to make it clear what you mean. See the matching algorithm discussion below.

For instance, define whether the tokens are case-sensitive.

@devd
devd commented Mar 22, 2016

I am probably missing a discussion somewhere but I am curious if we considered a token inside each *-src directive instead of creating a new directive. So, script-src ... 'block-non-sri' and similarly each directive could state whether it cares about sri. (sorry, if this has been discussed already; please point me to it)

@mikewest
Member

Ping? Is this going anywhere? Are you blocked on me or on something else? :)

@oreoshake

Not blocked, just life is getting in the way. This has been bumped from my todo list two weeks in a row ๐Ÿ˜ฟ

@mozfreddyb
Contributor

@oreoshake Would you be OK with someone else taking this pull request?

@oreoshake

@oreoshake Would you be OK with someone else taking this pull request?

@mozfreddyb I would be ecstatic if someone else handled this.

@shekyan
Contributor
shekyan commented Apr 27, 2016

I'd be happy to help. Have time till May 9.

@mozfreddyb
Contributor

Great! Just go ahead, Sergey!

@oreoshake oreoshake closed this May 18, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment