From b80db29a1dcb64efb304d2b047a3f3cae7c2076b Mon Sep 17 00:00:00 2001 From: Sid Stamm Date: Fri, 21 Jun 2013 16:43:07 -0700 Subject: [PATCH] Bug 764937 - make sure CSP 1.0 compliant parser infers "default-src *" when a default-src isn't specified (r=tanvi) --- content/base/src/CSPUtils.jsm | 20 ++++++--- content/base/test/unit/test_csputils.js | 57 +++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/content/base/src/CSPUtils.jsm b/content/base/src/CSPUtils.jsm index 9d17d5de7bd..d7bac0c9de7 100644 --- a/content/base/src/CSPUtils.jsm +++ b/content/base/src/CSPUtils.jsm @@ -838,17 +838,27 @@ CSPRep.prototype = { function cspsd_makeExplicit() { let SD = this._specCompliant ? CSPRep.SRC_DIRECTIVES_NEW : CSPRep.SRC_DIRECTIVES_OLD; - var defaultSrcDir = this._directives[SD.DEFAULT_SRC]; - // It's ok for a 1.0 spec compliant policy to not have a default source, // in this case it should use default-src * // However, our original CSP implementation required a default src // or an allow directive. - if (!defaultSrcDir && !this._specCompliant) { - this.log(WARN_FLAG, CSPLocalizer.getStr("allowOrDefaultSrcRequired")); - return false; + if (!this._directives[SD.DEFAULT_SRC]) { + if(!this._specCompliant) { + this.warn(CSPLocalizer.getStr("allowOrDefaultSrcRequired")); + return false; + } + + // bug 780978 will remove these lines and needs to make sure that + // CSPRep.permits() enforces this logic: prefixed headers default to + // "disallowed" and unprefixed headers default to "allowed" when + // neither specific -src nor default-src directive is provided. + this._directives[SD.DEFAULT_SRC] + = CSPSourceList.fromString("*", this, this._self, true); + this._directives[SD.DEFAULT_SRC]._isImplicit = true; } + var defaultSrcDir = this._directives[SD.DEFAULT_SRC]; + for (var dir in SD) { var dirv = SD[dir]; if (dirv === SD.DEFAULT_SRC) continue; diff --git a/content/base/test/unit/test_csputils.js b/content/base/test/unit/test_csputils.js index 2ae292745eb..7e55c8df15f 100644 --- a/content/base/test/unit/test_csputils.js +++ b/content/base/test/unit/test_csputils.js @@ -699,7 +699,7 @@ test(function test_FrameAncestor_ignores_userpass_bug779918() { // construct fake ancestry with CSP applied to the child. // [aChildUri] -> [aParentUri] -> (root/top) // and then test "permitsAncestry" on the child/self docshell. - function testPermits(aChildUri, aParentUri, aContext) { + function testPermits(aChildUri, aParentUri, aContentType) { let cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"] .createInstance(Ci.nsIContentSecurityPolicy); cspObj.refinePolicy(testPolicy, aChildUri, false); @@ -940,8 +940,8 @@ test( .createInstance(Ci.nsIContentSecurityPolicy); var selfURI = URI("http://self.com/"); - function testPermits(aUri, aContext) { - return cspObj.shouldLoad(aContext, aUri, null, null, null, null) + function testPermits(aUri, aContentType) { + return cspObj.shouldLoad(aContentType, aUri, null, null, null, null) == Ci.nsIContentPolicy.ACCEPT; }; @@ -982,6 +982,57 @@ test( Ci.nsIContentPolicy.TYPE_IMAGE)); }); +test( + function test_bug764937_defaultSrcMissing() { + var cspObjSpecCompliant = Cc["@mozilla.org/contentsecuritypolicy;1"] + .createInstance(Ci.nsIContentSecurityPolicy); + var cspObjOld = Cc["@mozilla.org/contentsecuritypolicy;1"] + .createInstance(Ci.nsIContentSecurityPolicy); + var selfURI = URI("http://self.com/"); + + function testPermits(cspObj, aUri, aContentType) { + return cspObj.shouldLoad(aContentType, aUri, null, null, null, null) + == Ci.nsIContentPolicy.ACCEPT; + }; + + const policy = "script-src 'self'"; + cspObjSpecCompliant.refinePolicy(policy, selfURI, true); + + // Spec-Compliant policy default-src defaults to *. + // This means all images are allowed, and only 'self' + // script is allowed. + do_check_true(testPermits(cspObjSpecCompliant, + URI("http://bar.com/foo.png"), + Ci.nsIContentPolicy.TYPE_IMAGE)); + do_check_true(testPermits(cspObjSpecCompliant, + URI("http://self.com/foo.png"), + Ci.nsIContentPolicy.TYPE_IMAGE)); + do_check_true(testPermits(cspObjSpecCompliant, + URI("http://self.com/foo.js"), + Ci.nsIContentPolicy.TYPE_SCRIPT)); + do_check_false(testPermits(cspObjSpecCompliant, + URI("http://bar.com/foo.js"), + Ci.nsIContentPolicy.TYPE_SCRIPT)); + + cspObjOld.refinePolicy(policy, selfURI, false); + + // non-Spec-Compliant policy default-src defaults to 'none' + // This means all images are blocked, and so are all scripts (because the + // policy is ignored and fails closed). + do_check_false(testPermits(cspObjOld, + URI("http://bar.com/foo.png"), + Ci.nsIContentPolicy.TYPE_IMAGE)); + do_check_false(testPermits(cspObjOld, + URI("http://self.com/foo.png"), + Ci.nsIContentPolicy.TYPE_IMAGE)); + do_check_false(testPermits(cspObjOld, + URI("http://self.com/foo.js"), + Ci.nsIContentPolicy.TYPE_SCRIPT)); + do_check_false(testPermits(cspObjOld, + URI("http://bar.com/foo.js"), + Ci.nsIContentPolicy.TYPE_SCRIPT)); + + }); /*