Bug 949533 - Remove uses of x-content-security-policy and pre-spec-compliant parsing/enforcement (file changes). r=jst,grobinson

--HG--
extra : rebase_source : 0be7ad6dc09ef5b6c273748af87503b7c0d19d5b
This commit is contained in:
Sid Stamm 2014-06-25 12:07:37 -07:00
parent b7e7fb40b8
commit b34ba073a6
16 changed files with 137 additions and 724 deletions

View File

@ -388,9 +388,6 @@ pref("content.ime.strict_policy", true);
// $ adb shell start
pref("browser.dom.window.dump.enabled", false);
// Turn on the CSP 1.0 parser for Content Security Policy headers
pref("security.csp.speccompliant", true);
// Default Content Security Policy to apply to privileged and certified apps
pref("security.apps.privileged.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'");
// If you change this CSP, make sure to update the fast path in nsCSPService.cpp

View File

@ -1524,9 +1524,6 @@ pref("social.sidebar.unload_timeout_ms", 10000);
pref("dom.identity.enabled", false);
// Turn on the CSP 1.0 parser for Content Security Policy headers
pref("security.csp.speccompliant", true);
// Block insecure active content on https pages
pref("security.mixed_content.block_active_content", true);

View File

@ -53,8 +53,6 @@ support-files =
test-bug-782653-css-errors-1.css
test-bug-782653-css-errors-2.css
test-bug-782653-css-errors.html
test-bug-821877-csperrors.html
test-bug-821877-csperrors.html^headers^
test-bug-837351-security-errors.html
test-bug-846918-hsts-invalid-headers.html
test-bug-846918-hsts-invalid-headers.html^headers^
@ -100,8 +98,6 @@ support-files =
test-repeated-messages.html
test-result-format-as-string.html
test-webconsole-error-observer.html
test_bug_770099_bad_policy_uri.html
test_bug_770099_bad_policy_uri.html^headers^
test_bug_770099_violation.html
test_bug_770099_violation.html^headers^
test-autocomplete-in-stackframe.html
@ -230,13 +226,11 @@ run-if = os == "win"
[browser_webconsole_bug_762593_insecure_passwords_web_console_warning.js]
[browser_webconsole_bug_764572_output_open_url.js]
[browser_webconsole_bug_766001_JS_Console_in_Debugger.js]
[browser_webconsole_bug_770099_bad_policyuri.js]
[browser_webconsole_bug_770099_violation.js]
[browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js]
[browser_webconsole_bug_804845_ctrl_key_nav.js]
run-if = os == "mac"
[browser_webconsole_bug_817834_add_edited_input_to_history.js]
[browser_webconsole_bug_821877_csp_errors.js]
[browser_webconsole_bug_837351_securityerrors.js]
[browser_webconsole_bug_846918_hsts_invalid-headers.js]
[browser_webconsole_bug_915141_toggle_response_logging_with_keyboard.js]

View File

@ -15,8 +15,8 @@ The expected console messages in the constants CSP_VIOLATION_MSG and CSP_REPORT_
*/
const TEST_VIOLATION = "http://example.com/browser/browser/devtools/webconsole/test/test_bug_1010953_cspro.html";
const CSP_VIOLATION_MSG = 'Content Security Policy: The page\'s settings blocked the loading of a resource at http://some.example.com/test.png ("img-src http://example.com:80").';
const CSP_REPORT_MSG = 'Content Security Policy: The page\'s settings observed the loading of a resource at http://some.example.com/test_bug_1010953_cspro.js ("script-src http://example.com:80"). A CSP report is being sent.';
const CSP_VIOLATION_MSG = 'Content Security Policy: The page\'s settings blocked the loading of a resource at http://some.example.com/test.png ("img-src http://example.com").';
const CSP_REPORT_MSG = 'Content Security Policy: The page\'s settings observed the loading of a resource at http://some.example.com/test_bug_1010953_cspro.js ("script-src http://example.com"). A CSP report is being sent.';
let hud = undefined;

View File

@ -8,7 +8,7 @@
// Tests that the Web Console CSP messages are displayed
const TEST_VIOLATION = "https://example.com/browser/browser/devtools/webconsole/test/test_bug_770099_violation.html";
const CSP_VIOLATION_MSG = 'Content Security Policy: The page\'s settings blocked the loading of a resource at http://some.example.com/test.png ("default-src https://example.com:443").'
const CSP_VIOLATION_MSG = 'Content Security Policy: The page\'s settings blocked the loading of a resource at http://some.example.com/test.png ("default-src https://example.com").'
let hud = undefined;

View File

@ -1 +1 @@
X-Content-Security-Policy: default-src 'self'
Content-Security-Policy: default-src 'self'

View File

@ -193,7 +193,7 @@ CSPPolicyURIListener.prototype = {
// send the policy we received back to the parent document's CSP
// for parsing
this._csp.appendPolicy(this._policy, this._docURI,
this._reportOnly, this._csp._specCompliant);
this._reportOnly, true);
}
else {
// problem fetching policy so fail closed by appending a "block it all"
@ -202,7 +202,7 @@ CSPPolicyURIListener.prototype = {
this._csp.log(WARN_FLAG, CSPLocalizer.getFormatStr("errorFetchingPolicy",
[status]));
this._csp.appendPolicy("default-src 'none'", this._docURI,
this._reportOnly, this._csp._specCompliant);
this._reportOnly, true);
}
// resume the parent document request
this._docRequest.resume();
@ -213,49 +213,23 @@ CSPPolicyURIListener.prototype = {
/**
* Class that represents a parsed policy structure.
*
* @param aSpecCompliant: true: this policy is a CSP 1.0 spec
* compliant policy and should be parsed as such.
* false or undefined: this is a policy using
* our original implementation's CSP syntax.
*/
this.CSPRep = function CSPRep(aSpecCompliant) {
this.CSPRep = function CSPRep() {
// this gets set to true when the policy is done parsing, or when a
// URI-borne policy has finished loading.
this._isInitialized = false;
this._allowEval = false;
this._allowInlineScripts = false;
this._allowInlineStyles = false;
this._reportOnlyMode = false;
// don't auto-populate _directives, so it is easier to find bugs
this._directives = {};
// Is this a 1.0 spec compliant CSPRep ?
// Default to false if not specified.
this._specCompliant = (aSpecCompliant !== undefined) ? aSpecCompliant : false;
// Only CSP 1.0 spec compliant policies block inline styles by default.
this._allowInlineStyles = !aSpecCompliant;
}
// Source directives for our original CSP implementation.
// These can be removed when the original implementation is deprecated.
CSPRep.SRC_DIRECTIVES_OLD = {
DEFAULT_SRC: "default-src",
SCRIPT_SRC: "script-src",
STYLE_SRC: "style-src",
MEDIA_SRC: "media-src",
IMG_SRC: "img-src",
OBJECT_SRC: "object-src",
FRAME_SRC: "frame-src",
FRAME_ANCESTORS: "frame-ancestors",
FONT_SRC: "font-src",
XHR_SRC: "xhr-src"
};
// Source directives for our CSP 1.0 spec compliant implementation.
CSPRep.SRC_DIRECTIVES_NEW = {
CSPRep.SRC_DIRECTIVES = {
DEFAULT_SRC: "default-src",
SCRIPT_SRC: "script-src",
STYLE_SRC: "style-src",
@ -273,268 +247,6 @@ CSPRep.URI_DIRECTIVES = {
POLICY_URI: "policy-uri" /* single URI */
};
// These directives no longer exist in CSP 1.0 and
// later and will eventually be removed when we no longer
// support our original implementation's syntax.
CSPRep.OPTIONS_DIRECTIVE = "options";
CSPRep.ALLOW_DIRECTIVE = "allow";
/**
* Factory to create a new CSPRep, parsed from a string.
*
* @param aStr
* string rep of a CSP
* @param self (optional)
* URI representing the "self" source
* @param reportOnly (optional)
* whether or not this CSP is report-only (defaults to false)
* @param docRequest (optional)
* request for the parent document which may need to be suspended
* while the policy-uri is asynchronously fetched
* @param csp (optional)
* the CSP object to update once the policy has been fetched
* @param enforceSelfChecks (optional)
* if present, and "true", will check to be sure "self" has the
* appropriate values to inherit when they are omitted from the source.
* @returns
* an instance of CSPRep
*/
CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp,
enforceSelfChecks) {
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var UD = CSPRep.URI_DIRECTIVES;
var aCSPR = new CSPRep();
aCSPR._originalText = aStr;
aCSPR._innerWindowID = innerWindowFromRequest(docRequest);
if (typeof reportOnly === 'undefined') reportOnly = false;
aCSPR._reportOnlyMode = reportOnly;
var selfUri = null;
if (self instanceof Ci.nsIURI) {
selfUri = self.cloneIgnoringRef();
// clean userpass out of the URI (not used for CSP origin checking, but
// shows up in prePath).
try {
// GetUserPass throws for some protocols without userPass
selfUri.userPass = '';
} catch (ex) {}
}
var dirs = aStr.split(";");
directive:
for each(var dir in dirs) {
dir = dir.trim();
if (dir.length < 1) continue;
var dirname = dir.split(/\s+/)[0].toLowerCase();
var dirvalue = dir.substring(dirname.length).trim();
if (aCSPR._directives.hasOwnProperty(dirname)) {
// Check for (most) duplicate directives
cspError(aCSPR, CSPLocalizer.getFormatStr("duplicateDirective",
[dirname]));
CSPdebug("Skipping duplicate directive: \"" + dir + "\"");
continue directive;
}
// OPTIONS DIRECTIVE ////////////////////////////////////////////////
if (dirname === CSPRep.OPTIONS_DIRECTIVE) {
if (aCSPR._allowInlineScripts || aCSPR._allowEval) {
// Check for duplicate options directives
cspError(aCSPR, CSPLocalizer.getFormatStr("duplicateDirective",
[dirname]));
CSPdebug("Skipping duplicate directive: \"" + dir + "\"");
continue directive;
}
// grab value tokens and interpret them
var options = dirvalue.split(/\s+/);
for each (var opt in options) {
if (opt === "inline-script")
aCSPR._allowInlineScripts = true;
else if (opt === "eval-script")
aCSPR._allowEval = true;
else
cspWarn(aCSPR, CSPLocalizer.getFormatStr("ignoringUnknownOption",
[opt]));
}
continue directive;
}
// ALLOW DIRECTIVE //////////////////////////////////////////////////
// parse "allow" as equivalent to "default-src", at least until the spec
// stabilizes, at which time we can stop parsing "allow"
if (dirname === CSPRep.ALLOW_DIRECTIVE) {
cspWarn(aCSPR, CSPLocalizer.getStr("allowDirectiveIsDeprecated"));
if (aCSPR._directives.hasOwnProperty(SD.DEFAULT_SRC)) {
// Check for duplicate default-src and allow directives
cspError(aCSPR, CSPLocalizer.getFormatStr("duplicateDirective",
[dirname]));
CSPdebug("Skipping duplicate directive: \"" + dir + "\"");
continue directive;
}
var dv = CSPSourceList.fromString(dirvalue, aCSPR, selfUri,
enforceSelfChecks);
if (dv) {
aCSPR._directives[SD.DEFAULT_SRC] = dv;
continue directive;
}
}
// SOURCE DIRECTIVES ////////////////////////////////////////////////
for each(var sdi in SD) {
if (dirname === sdi) {
// process dirs, and enforce that 'self' is defined.
var dv = CSPSourceList.fromString(dirvalue, aCSPR, selfUri,
enforceSelfChecks);
if (dv) {
aCSPR._directives[sdi] = dv;
continue directive;
}
}
}
// REPORT URI ///////////////////////////////////////////////////////
if (dirname === UD.REPORT_URI) {
// might be space-separated list of URIs
var uriStrings = dirvalue.split(/\s+/);
var okUriStrings = [];
for (let i in uriStrings) {
var uri = null;
try {
// Relative URIs are okay, but to ensure we send the reports to the
// right spot, the relative URIs are expanded here during parsing.
// The resulting CSPRep instance will have only absolute URIs.
uri = gIoService.newURI(uriStrings[i],null,selfUri);
// if there's no host, this will throw NS_ERROR_FAILURE, causing a
// parse failure.
uri.host;
// warn about, but do not prohibit non-http and non-https schemes for
// reporting URIs. The spec allows unrestricted URIs resolved
// relative to "self", but we should let devs know if the scheme is
// abnormal and may fail a POST.
if (!uri.schemeIs("http") && !uri.schemeIs("https")) {
cspWarn(aCSPR, CSPLocalizer.getFormatStr("reportURInotHttpsOrHttp2",
[uri.asciiSpec]));
}
} catch(e) {
switch (e.result) {
case Components.results.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS:
case Components.results.NS_ERROR_HOST_IS_IP_ADDRESS:
if (uri.host !== selfUri.host) {
cspWarn(aCSPR,
CSPLocalizer.getFormatStr("pageCannotSendReportsTo",
[selfUri.host, uri.host]));
continue;
}
break;
default:
cspWarn(aCSPR, CSPLocalizer.getFormatStr("couldNotParseReportURI",
[uriStrings[i]]));
continue;
}
}
// all verification passed
okUriStrings.push(uri.asciiSpec);
}
aCSPR._directives[UD.REPORT_URI] = okUriStrings.join(' ');
continue directive;
}
// POLICY URI //////////////////////////////////////////////////////////
if (dirname === UD.POLICY_URI) {
// POLICY_URI can only be alone
if (aCSPR._directives.length > 0 || dirs.length > 1) {
cspError(aCSPR, CSPLocalizer.getStr("policyURINotAlone"));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
// if we were called without a reference to the parent document request
// we won't be able to suspend it while we fetch the policy -> fail closed
if (!docRequest || !csp) {
cspError(aCSPR, CSPLocalizer.getStr("noParentRequest"));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
var uri = '';
try {
uri = gIoService.newURI(dirvalue, null, selfUri);
} catch(e) {
cspError(aCSPR, CSPLocalizer.getFormatStr("policyURIParseError",
[dirvalue]));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
// Verify that policy URI comes from the same origin
if (selfUri) {
if (selfUri.host !== uri.host) {
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingHost",
[uri.host]));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
if (selfUri.port !== uri.port) {
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingPort",
[uri.port.toString()]));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
if (selfUri.scheme !== uri.scheme) {
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingScheme",
[uri.scheme]));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
}
// suspend the parent document request while we fetch the policy-uri
try {
docRequest.suspend();
var chan = gIoService.newChannel(uri.asciiSpec, null, null);
// make request anonymous (no cookies, etc.) so the request for the
// policy-uri can't be abused for CSRF
chan.loadFlags |= Ci.nsIChannel.LOAD_ANONYMOUS;
chan.loadGroup = docRequest.loadGroup;
chan.asyncOpen(new CSPPolicyURIListener(uri, docRequest, csp, reportOnly), null);
}
catch (e) {
// resume the document request and apply most restrictive policy
docRequest.resume();
cspError(aCSPR, CSPLocalizer.getFormatStr("errorFetchingPolicy",
[e.toString()]));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
// return a fully-open policy to be used until the contents of the
// policy-uri come back.
return CSPRep.fromString("default-src *", null, reportOnly);
}
// UNIDENTIFIED DIRECTIVE /////////////////////////////////////////////
cspWarn(aCSPR, CSPLocalizer.getFormatStr("couldNotProcessUnknownDirective",
[dirname]));
} // end directive: loop
// the X-Content-Security-Policy syntax requires an allow or default-src
// directive to be present.
if (!aCSPR._directives[SD.DEFAULT_SRC]) {
cspWarn(aCSPR, CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
// If this is a Report-Only header and report-uri is not in the directive
// list, tell developer either specify report-uri directive or use
// a non-Report-Only CSP header.
if (aCSPR._reportOnlyMode && !aCSPR._directives.hasOwnProperty(UD.REPORT_URI)) {
cspWarn(aCSPR, CSPLocalizer.getFormatStr("reportURInotInReportOnlyHeader",
[selfUri ? selfUri.prePath : "undefined"]))
}
return aCSPR;
};
/**
* Factory to create a new CSPRep, parsed from a string, compliant
* with the CSP 1.0 spec.
@ -556,13 +268,11 @@ CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp,
* @returns
* an instance of CSPRep
*/
// When we deprecate our original CSP implementation, we rename this to
// CSPRep.fromString and remove the existing CSPRep.fromString above.
CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, csp,
enforceSelfChecks) {
var SD = CSPRep.SRC_DIRECTIVES_NEW;
CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp,
enforceSelfChecks) {
var SD = CSPRep.SRC_DIRECTIVES;
var UD = CSPRep.URI_DIRECTIVES;
var aCSPR = new CSPRep(true);
var aCSPR = new CSPRep();
aCSPR._originalText = aStr;
aCSPR._innerWindowID = innerWindowFromRequest(docRequest);
if (typeof reportOnly === 'undefined') reportOnly = false;
@ -587,7 +297,10 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, cs
var dirname = dir.split(/\s+/)[0].toLowerCase();
var dirvalue = dir.substring(dirname.length).trim();
dirs[dirname] = dirvalue;
// skip duplicates
if (!dirs.hasOwnProperty(dirname)) {
dirs[dirname] = dirvalue;
}
}
// Spec compliant policies have different default behavior for inline
@ -712,13 +425,13 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, cs
// POLICY_URI can only be alone
if (aCSPR._directives.length > 0 || dirs.length > 1) {
cspError(aCSPR, CSPLocalizer.getStr("policyURINotAlone"));
return CSPRep.fromStringSpecCompliant("default-src 'none'", null, reportOnly);
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
// if we were called without a reference to the parent document request
// we won't be able to suspend it while we fetch the policy -> fail closed
if (!docRequest || !csp) {
cspError(aCSPR, CSPLocalizer.getStr("noParentRequest"));
return CSPRep.fromStringSpecCompliant("default-src 'none'", null, reportOnly);
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
var uri = '';
@ -726,22 +439,22 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, cs
uri = gIoService.newURI(dirvalue, null, selfUri);
} catch(e) {
cspError(aCSPR, CSPLocalizer.getFormatStr("policyURIParseError", [dirvalue]));
return CSPRep.fromStringSpecCompliant("default-src 'none'", null, reportOnly);
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
// Verify that policy URI comes from the same origin
if (selfUri) {
if (selfUri.host !== uri.host){
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingHost", [uri.host]));
return CSPRep.fromStringSpecCompliant("default-src 'none'", null, reportOnly);
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
if (selfUri.port !== uri.port){
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingPort", [uri.port.toString()]));
return CSPRep.fromStringSpecCompliant("default-src 'none'", null, reportOnly);
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
if (selfUri.scheme !== uri.scheme){
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingScheme", [uri.scheme]));
return CSPRep.fromStringSpecCompliant("default-src 'none'", null, reportOnly);
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
}
@ -759,12 +472,12 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, cs
// resume the document request and apply most restrictive policy
docRequest.resume();
cspError(aCSPR, CSPLocalizer.getFormatStr("errorFetchingPolicy", [e.toString()]));
return CSPRep.fromStringSpecCompliant("default-src 'none'", null, reportOnly);
return CSPRep.fromString("default-src 'none'", null, reportOnly);
}
// return a fully-open policy to be used until the contents of the
// policy-uri come back
return CSPRep.fromStringSpecCompliant("default-src *", null, reportOnly);
return CSPRep.fromString("default-src *", null, reportOnly);
}
// UNIDENTIFIED DIRECTIVE /////////////////////////////////////////////
@ -819,10 +532,6 @@ CSPRep.prototype = {
function csp_toString() {
var dirs = [];
if (!this._specCompliant && (this._allowEval || this._allowInlineScripts)) {
dirs.push("options" + (this._allowEval ? " eval-script" : "")
+ (this._allowInlineScripts ? " inline-script" : ""));
}
for (var i in this._directives) {
if (this._directives[i]) {
dirs.push(i + " " + this._directives[i].toString());
@ -867,7 +576,7 @@ CSPRep.prototype = {
return true;
// make sure the right directive set is used
let DIRS = this._specCompliant ? CSPRep.SRC_DIRECTIVES_NEW : CSPRep.SRC_DIRECTIVES_OLD;
let DIRS = CSPRep.SRC_DIRECTIVES;
let directiveInPolicy = false;
for (var i in DIRS) {
@ -904,8 +613,8 @@ CSPRep.prototype = {
}
// no relevant directives present -- this means for CSP 1.0 that the load
// should be permitted (and for the old CSP, to block it).
return this._specCompliant;
// should be permitted.
return true;
},
/**
@ -1541,7 +1250,11 @@ CSPSource.prototype = {
s = s + this.scheme + "://";
if (this._host)
s = s + this._host;
if (this.port)
// CSP 1.0 4.11 says the report should use URI-reference from RFC 3986,
// 3.2.3 and indicates that the default port should be omitted.
// Non-default ports are included.
if (this.port && gIoService.getProtocolHandler(this.scheme).defaultPort != this.port)
s = s + ":" + this.port;
return s;
},

View File

@ -24,11 +24,6 @@ const Cu = Components.utils;
const CSP_VIOLATION_TOPIC = "csp-on-violate-policy";
// Needed to support CSP 1.0 spec and our original CSP implementation - should
// be removed when our original implementation is deprecated.
const CSP_TYPE_XMLHTTPREQUEST_SPEC_COMPLIANT = "csp_type_xmlhttprequest_spec_compliant";
const CSP_TYPE_WEBSOCKET_SPEC_COMPLIANT = "csp_type_websocket_spec_compliant";
const WARN_FLAG = Ci.nsIScriptError.warningFlag;
const ERROR_FLAG = Ci.nsIScriptError.ERROR_FLAG;
@ -71,14 +66,13 @@ function ContentSecurityPolicy() {
{
let cp = Ci.nsIContentPolicy;
let csp = ContentSecurityPolicy;
let cspr_sd_old = CSPRep.SRC_DIRECTIVES_OLD;
let cspr_sd_new = CSPRep.SRC_DIRECTIVES_NEW;
let cspr_sd = CSPRep.SRC_DIRECTIVES;
csp._MAPPINGS=[];
/* default, catch-all case */
// This is the same in old and new CSP so use the new mapping.
csp._MAPPINGS[cp.TYPE_OTHER] = cspr_sd_new.DEFAULT_SRC;
csp._MAPPINGS[cp.TYPE_OTHER] = cspr_sd.DEFAULT_SRC;
/* self */
csp._MAPPINGS[cp.TYPE_DOCUMENT] = null;
@ -87,44 +81,26 @@ function ContentSecurityPolicy() {
csp._MAPPINGS[cp.TYPE_REFRESH] = null;
/* categorized content types */
// These are the same in old and new CSP's so just use the new mappings.
csp._MAPPINGS[cp.TYPE_SCRIPT] = cspr_sd_new.SCRIPT_SRC;
csp._MAPPINGS[cp.TYPE_IMAGE] = cspr_sd_new.IMG_SRC;
csp._MAPPINGS[cp.TYPE_STYLESHEET] = cspr_sd_new.STYLE_SRC;
csp._MAPPINGS[cp.TYPE_OBJECT] = cspr_sd_new.OBJECT_SRC;
csp._MAPPINGS[cp.TYPE_OBJECT_SUBREQUEST] = cspr_sd_new.OBJECT_SRC;
csp._MAPPINGS[cp.TYPE_SUBDOCUMENT] = cspr_sd_new.FRAME_SRC;
csp._MAPPINGS[cp.TYPE_MEDIA] = cspr_sd_new.MEDIA_SRC;
csp._MAPPINGS[cp.TYPE_FONT] = cspr_sd_new.FONT_SRC;
csp._MAPPINGS[cp.TYPE_XSLT] = cspr_sd_new.SCRIPT_SRC;
csp._MAPPINGS[cp.TYPE_BEACON] = cspr_sd_new.CONNECT_SRC;
/* Our original CSP implementation's mappings for XHR and websocket
* These should be changed to be = cspr_sd.CONNECT_SRC when we remove
* the original implementation - NOTE: order in this array is important !!!
*/
csp._MAPPINGS[cp.TYPE_XMLHTTPREQUEST] = cspr_sd_old.XHR_SRC;
csp._MAPPINGS[cp.TYPE_WEBSOCKET] = cspr_sd_old.XHR_SRC;
csp._MAPPINGS[cp.TYPE_SCRIPT] = cspr_sd.SCRIPT_SRC;
csp._MAPPINGS[cp.TYPE_IMAGE] = cspr_sd.IMG_SRC;
csp._MAPPINGS[cp.TYPE_STYLESHEET] = cspr_sd.STYLE_SRC;
csp._MAPPINGS[cp.TYPE_OBJECT] = cspr_sd.OBJECT_SRC;
csp._MAPPINGS[cp.TYPE_OBJECT_SUBREQUEST] = cspr_sd.OBJECT_SRC;
csp._MAPPINGS[cp.TYPE_SUBDOCUMENT] = cspr_sd.FRAME_SRC;
csp._MAPPINGS[cp.TYPE_MEDIA] = cspr_sd.MEDIA_SRC;
csp._MAPPINGS[cp.TYPE_FONT] = cspr_sd.FONT_SRC;
csp._MAPPINGS[cp.TYPE_XSLT] = cspr_sd.SCRIPT_SRC;
csp._MAPPINGS[cp.TYPE_BEACON] = cspr_sd.CONNECT_SRC;
csp._MAPPINGS[cp.TYPE_XMLHTTPREQUEST] = cspr_sd.CONNECT_SRC;
csp._MAPPINGS[cp.TYPE_WEBSOCKET] = cspr_sd.CONNECT_SRC;
/* CSP cannot block CSP reports */
csp._MAPPINGS[cp.TYPE_CSP_REPORT] = null;
/* These must go through the catch-all */
csp._MAPPINGS[cp.TYPE_XBL] = cspr_sd_new.DEFAULT_SRC;
csp._MAPPINGS[cp.TYPE_PING] = cspr_sd_new.DEFAULT_SRC;
csp._MAPPINGS[cp.TYPE_DTD] = cspr_sd_new.DEFAULT_SRC;
/* CSP 1.0 spec compliant mappings for XHR and websocket */
// The directive name for XHR, websocket, and EventSource is different
// in the 1.0 spec than in our original implementation, these mappings
// address this. These won't be needed when we deprecate our original
// implementation.
csp._MAPPINGS[CSP_TYPE_XMLHTTPREQUEST_SPEC_COMPLIANT] = cspr_sd_new.CONNECT_SRC;
csp._MAPPINGS[CSP_TYPE_WEBSOCKET_SPEC_COMPLIANT] = cspr_sd_new.CONNECT_SRC;
// TODO : EventSource will be here and also will use connect-src
// after we fix Bug 802872 - CSP should restrict EventSource using the connect-src
// directive. For background see Bug 667490 - EventSource should use the same
// nsIContentPolicy type as XHR (which is fixed)
csp._MAPPINGS[cp.TYPE_XBL] = cspr_sd.DEFAULT_SRC;
csp._MAPPINGS[cp.TYPE_PING] = cspr_sd.DEFAULT_SRC;
csp._MAPPINGS[cp.TYPE_DTD] = cspr_sd.DEFAULT_SRC;
}
ContentSecurityPolicy.prototype = {
@ -157,7 +133,7 @@ ContentSecurityPolicy.prototype = {
_buildViolatedDirectiveString:
function(aDirectiveName, aPolicy) {
var SD = CSPRep.SRC_DIRECTIVES_NEW;
var SD = CSPRep.SRC_DIRECTIVES;
var cspContext = (SD[aDirectiveName] in aPolicy._directives) ? SD[aDirectiveName] : SD.DEFAULT_SRC;
var directive = aPolicy._directives[cspContext];
return cspContext + ' ' + directive.toString();
@ -410,8 +386,7 @@ ContentSecurityPolicy.prototype = {
*/
appendPolicy:
function csp_appendPolicy(aPolicy, selfURI, aReportOnly, aSpecCompliant) {
return this._appendPolicyInternal(aPolicy, selfURI, aReportOnly,
aSpecCompliant, true);
return this._appendPolicyInternal(aPolicy, selfURI, aReportOnly, true);
},
/**
@ -420,12 +395,10 @@ ContentSecurityPolicy.prototype = {
* @returns the count of policies.
*/
_appendPolicyInternal:
function csp_appendPolicy(aPolicy, selfURI, aReportOnly, aSpecCompliant,
aEnforceSelfChecks) {
function csp_appendPolicy(aPolicy, selfURI, aReportOnly, aEnforceSelfChecks) {
#ifndef MOZ_B2G
CSPdebug("APPENDING POLICY: " + aPolicy);
CSPdebug(" SELF: " + (selfURI ? selfURI.asciiSpec : " null"));
CSPdebug("CSP 1.0 COMPLIANT : " + aSpecCompliant);
#endif
// For nested schemes such as view-source: make sure we are taking the
@ -446,26 +419,9 @@ ContentSecurityPolicy.prototype = {
// Note that we pass the full URI since when it's parsed as 'self' to construct a
// CSPSource only the scheme, host, and port are kept.
// If we want to be CSP 1.0 spec compliant, use the new parser.
// The old one will be deprecated in the future and will be
// removed at that time.
if (aSpecCompliant) {
newpolicy = CSPRep.fromStringSpecCompliant(aPolicy,
selfURI,
aReportOnly,
this._weakDocRequest.get(),
this,
aEnforceSelfChecks);
} else {
newpolicy = CSPRep.fromString(aPolicy,
selfURI,
aReportOnly,
this._weakDocRequest.get(),
this,
aEnforceSelfChecks);
}
newpolicy._specCompliant = !!aSpecCompliant;
newpolicy = CSPRep.fromString(aPolicy, selfURI, aReportOnly,
this._weakDocRequest.get(),
this, aEnforceSelfChecks);
newpolicy._isInitialized = true;
this._policies.push(newpolicy);
this._cache.clear(); // reset cache since effective policy changes
@ -711,7 +667,7 @@ ContentSecurityPolicy.prototype = {
// scan the discovered ancestors
// frame-ancestors is the same in both old and new source directives,
// so don't need to differentiate here.
let cspContext = CSPRep.SRC_DIRECTIVES_NEW.FRAME_ANCESTORS;
let cspContext = CSPRep.SRC_DIRECTIVES.FRAME_ANCESTORS;
for (let i in ancestors) {
let ancestor = ancestors[i];
if (!policy.permits(ancestor, cspContext)) {
@ -806,22 +762,11 @@ ContentSecurityPolicy.prototype = {
for (let policyIndex=0; policyIndex < this._policies.length; policyIndex++) {
let policy = this._policies[policyIndex];
cspContext = ContentSecurityPolicy._MAPPINGS[aContentType];
#ifndef MOZ_B2G
CSPdebug("policy is " + (policy._specCompliant ?
"1.0 compliant" : "pre-1.0"));
CSPdebug("policy is " + (policy._reportOnlyMode ?
"report-only" : "blocking"));
#endif
if (aContentType == cp.TYPE_XMLHTTPREQUEST && this._policies[policyIndex]._specCompliant) {
cspContext = ContentSecurityPolicy._MAPPINGS[CSP_TYPE_XMLHTTPREQUEST_SPEC_COMPLIANT];
} else if (aContentType == cp.TYPE_WEBSOCKET && this._policies[policyIndex]._specCompliant) {
cspContext = ContentSecurityPolicy._MAPPINGS[CSP_TYPE_WEBSOCKET_SPEC_COMPLIANT];
} else {
cspContext = ContentSecurityPolicy._MAPPINGS[aContentType];
}
#ifndef MOZ_B2G
CSPdebug("shouldLoad cspContext = " + cspContext);
#endif
@ -979,11 +924,9 @@ ContentSecurityPolicy.prototype = {
for (let pCount = aStream.read32(); pCount > 0; pCount--) {
let polStr = aStream.readString();
let reportOnly = aStream.readBoolean();
let specCompliant = aStream.readBoolean();
// don't need self info because when the policy is turned back into a
// string, 'self' is replaced with the explicit source expression.
this._appendPolicyInternal(polStr, null, reportOnly, specCompliant,
false);
this._appendPolicyInternal(polStr, null, reportOnly, false);
}
// NOTE: the document instance that's deserializing this object (via its
@ -1010,7 +953,6 @@ ContentSecurityPolicy.prototype = {
for each (var policy in this._policies) {
aStream.writeWStringZ(policy.toString());
aStream.writeBoolean(policy._reportOnlyMode);
aStream.writeBoolean(policy._specCompliant);
}
},
};

View File

@ -2682,18 +2682,9 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
nsAutoCString tCspHeaderValue, tCspROHeaderValue;
nsAutoCString tCspOldHeaderValue, tCspOldROHeaderValue;
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
if (httpChannel) {
httpChannel->GetResponseHeader(
NS_LITERAL_CSTRING("x-content-security-policy"),
tCspOldHeaderValue);
httpChannel->GetResponseHeader(
NS_LITERAL_CSTRING("x-content-security-policy-report-only"),
tCspOldROHeaderValue);
httpChannel->GetResponseHeader(
NS_LITERAL_CSTRING("content-security-policy"),
tCspHeaderValue);
@ -2704,35 +2695,6 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
NS_ConvertASCIItoUTF16 cspOldHeaderValue(tCspOldHeaderValue);
NS_ConvertASCIItoUTF16 cspOldROHeaderValue(tCspOldROHeaderValue);
// Only use the CSP 1.0 spec compliant headers if a pref to do so
// is set. This lets us turn on the 1.0 parser per platform. This
// pref is also set by the tests for 1.0 spec compliant CSP.
bool specCompliantEnabled =
Preferences::GetBool("security.csp.speccompliant");
// If spec compliant pref isn't set, pretend we never got these headers.
if ((!cspHeaderValue.IsEmpty() || !cspROHeaderValue.IsEmpty()) &&
!specCompliantEnabled) {
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
("Got spec compliant CSP headers but pref was not set"));
cspHeaderValue.Truncate();
cspROHeaderValue.Truncate();
}
// If both the new header AND the old header are present, warn that
// the old header will be ignored. Otherwise, if the old header is
// present, warn that it will be deprecated.
bool oldHeaderIsPresent = !cspOldHeaderValue.IsEmpty() || !cspOldROHeaderValue.IsEmpty();
bool newHeaderIsPresent = !cspHeaderValue.IsEmpty() || !cspROHeaderValue.IsEmpty();
if (oldHeaderIsPresent && newHeaderIsPresent) {
mCSPWebConsoleErrorQueue.Add("BothCSPHeadersPresent");
} else if (oldHeaderIsPresent) {
mCSPWebConsoleErrorQueue.Add("OldCSPHeaderDeprecated");
}
// Figure out if we need to apply an app default CSP or a CSP from an app manifest
nsIPrincipal* principal = NodePrincipal();
@ -2760,9 +2722,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
if (!applyAppDefaultCSP &&
!applyAppManifestCSP &&
cspHeaderValue.IsEmpty() &&
cspROHeaderValue.IsEmpty() &&
cspOldHeaderValue.IsEmpty() &&
cspOldROHeaderValue.IsEmpty()) {
cspROHeaderValue.IsEmpty()) {
#ifdef PR_LOGGING
nsCOMPtr<nsIURI> chanURI;
aChannel->GetURI(getter_AddRefs(chanURI));
@ -2812,7 +2772,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
// * however, we still support XCSP headers during the transition phase
// and fall back to the JS implementation if we find an XCSP header.
if (newHeaderIsPresent && CSPService::sNewBackendEnabled) {
if (CSPService::sNewBackendEnabled) {
csp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
}
else {
@ -2845,36 +2805,25 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
if (appCSP) {
// Use the 1.0 CSP parser for apps if the pref to do so is set.
csp->AppendPolicy(appCSP, selfURI, false, specCompliantEnabled);
csp->AppendPolicy(appCSP, selfURI, false, true);
}
}
// ----- if the doc is an app and specifies a CSP in its manifest, apply it.
if (applyAppManifestCSP) {
// Use the 1.0 CSP parser for apps if the pref to do so is set.
csp->AppendPolicy(appManifestCSP, selfURI, false, specCompliantEnabled);
csp->AppendPolicy(appManifestCSP, selfURI, false, true);
}
// While we are supporting both CSP 1.0 and the x- headers, the 1.0 headers
// take priority. If both are present, the x-* headers are ignored.
// ----- if there's a full-strength CSP header, apply it.
if (!cspHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspHeaderValue, selfURI, false, true);
NS_ENSURE_SUCCESS(rv, rv);
} else if (!cspOldHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspOldHeaderValue, selfURI, false, false);
NS_ENSURE_SUCCESS(rv, rv);
}
// ----- if there's a report-only CSP header, apply it.
if (!cspROHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspROHeaderValue, selfURI, true, true);
NS_ENSURE_SUCCESS(rv, rv);
} else if (!cspOldROHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspOldROHeaderValue, selfURI, true, false);
NS_ENSURE_SUCCESS(rv, rv);
}
// ----- Enforce frame-ancestor policy on any applied policies

View File

@ -6,7 +6,6 @@
TEST_TOOL_DIRS += [
'csp',
'xcsp',
'websocket_hybi',
]

View File

@ -27,7 +27,7 @@ function testValidSRCsHostSourceWithSchemeAndPath() {
]
var obj;
var expected = "http://test1.example.com:80";
var expected = "http://test1.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
@ -53,7 +53,7 @@ function testValidSRCsRegularHost() {
]
var obj;
var expected = "http://test1.example.com:80";
var expected = "http://test1.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
@ -77,7 +77,7 @@ function testValidSRCsWildCardHost() {
]
var obj;
var expected = "http://*.example.com:80";
var expected = "http://*.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
@ -99,7 +99,7 @@ function testValidSRCsRegularPort() {
]
var obj;
var expected = "http://test1.example.com:80";
var expected = "http://test1.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);

View File

@ -63,8 +63,9 @@ function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
// set up a new CSP instance for each test.
var csp = Cc["@mozilla.org/contentsecuritypolicy;1"]
//var csp = Cc["@mozilla.org/cspcontext;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
var policy = "allow 'none'; " +
var policy = "default-src 'none'; " +
"report-uri " + REPORT_SERVER_URI +
":" + REPORT_SERVER_PORT +
"/test" + id;
@ -80,7 +81,7 @@ function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
// Load up the policy
// set as report-only if that's the case
csp.appendPolicy(policy, selfuri, useReportOnlyPolicy, false);
csp.appendPolicy(policy, selfuri, useReportOnlyPolicy, true);
// prime the report server
var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON);

View File

@ -35,7 +35,7 @@ function do_check_in_array(arr, val, stack) {
var text = val + " in [" + arr.join(",") + "]";
for(var i in arr) {
dump(".......... " + i + "> " + arr[i] + "\n");
//dump(".......... " + i + "> " + arr[i] + "\n");
if(arr[i] == val) {
//succeed
++_passedChecks;
@ -261,7 +261,7 @@ test(
test(
function test_CSPSourceList_fromString_twohost() {
var str = "foo.bar:21 https://ras.bar";
var parsed = "http://foo.bar:21 https://ras.bar:443";
var parsed = "http://foo.bar:21 https://ras.bar";
var sd = CSPSourceList.fromString(str, undefined, URI("http://self.com:80"));
//"two-host list should parse"
do_check_neq(null,sd);
@ -321,43 +321,26 @@ test(
do_check_false(wildcardHostSourceList.permits("http://barbaz.com"));
});
///////////////////// Test the Whole CSP rep object //////////////////////
//////////////// TEST CSP REP SPEC COMPLIANT PARSER ////////////
test(
function test_CSPRep_fromString() {
// check default init
//ASSERT(!(new CSPRep())._isInitialized, "Uninitialized rep thinks it is.")
var cspr;
var cspr_allowval;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var SD = CSPRep.SRC_DIRECTIVES;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.SCRIPT_SRC, SD.FONT_SRC,
SD.OBJECT_SRC, SD.FRAME_SRC, SD.CONNECT_SRC];
// check default policy "allow *"
cspr = CSPRep.fromString("allow *", URI("http://self.com:80"));
// "DEFAULT_SRC directive is missing when specified in fromString"
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
});
test(
function test_CSPRep_defaultSrc() {
var cspr, cspr_default_val, cspr_allow;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
// apply policy of "default-src *" (e.g. "allow *")
// check default policy "default-src *"
cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
// "DEFAULT_SRC directive is missing when specified in fromString"
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
// check that |allow *| and |default-src *| are parsed equivalently and
// result in the same set of explicit policy directives
cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
cspr_allow = CSPRep.fromString("allow *", URI("http://self.com:80"));
do_check_equivalent(cspr._directives['default-src'],
cspr_allow._directives['default-src']);
for(var x in DEFAULTS) {
// each of these should be equivalent to DEFAULT_SRC
//DEFAULTS[x] + " does not use default rule."
do_check_true(cspr.permits("http://bar.com", DEFAULTS[x]));
}
});
@ -365,11 +348,12 @@ test(
function test_CSPRep_fromString_oneDir() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.FRAME_SRC];
var SD = CSPRep.SRC_DIRECTIVES;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC,
SD.FRAME_SRC, SD.CONNECT_SRC];
// check one-directive policies
cspr = CSPRep.fromString("allow bar.com; script-src https://foo.com",
cspr = CSPRep.fromString("default-src bar.com; script-src https://foo.com",
URI("http://self.com"));
for(var x in DEFAULTS) {
@ -389,15 +373,18 @@ test(
});
test(
function test_CSPRep_fromString_twodir() {
function test_CSPRep_fromString_twoDir() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC];
var SD = CSPRep.SRC_DIRECTIVES;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC,
SD.CONNECT_SRC];
// check two-directive policies
var polstr = "allow allow.com; "
+ "script-src https://foo.com; "
+ "img-src bar.com:*";
var polstr = "default-src allow.com; " +
"script-src https://foo.com; " +
"img-src bar.com:*";
cspr = CSPRep.fromString(polstr, URI("http://self.com"));
for(var x in DEFAULTS) {
@ -425,123 +412,12 @@ test(
test(function test_CSPRep_fromString_withself() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var self = "https://self.com:34";
var SD = CSPRep.SRC_DIRECTIVES;
// check one-directive policies
cspr = CSPRep.fromString("allow 'self'; script-src 'self' https://*:*",
URI(self));
//"img-src does not enforce default rule, 'self'.
do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
//"img-src does not allow self
do_check_true(cspr.permits(self, SD.IMG_SRC));
//"script-src is too relaxed
do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC));
//"script-src should allow self
do_check_true(cspr.permits(self, SD.SCRIPT_SRC));
//"script-src is too strict on host/port
do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC));
});
//////////////// TEST CSP REP SPEC COMPLIANT PARSER ////////////
test(
function test_CSPRep_fromStringSpecCompliant() {
var cspr;
var cspr_allowval;
var SD = CSPRep.SRC_DIRECTIVES_NEW;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.SCRIPT_SRC, SD.FONT_SRC,
SD.OBJECT_SRC, SD.FRAME_SRC, SD.CONNECT_SRC];
// check default policy "default-src *"
cspr = CSPRep.fromStringSpecCompliant("default-src *", URI("http://self.com:80"));
// "DEFAULT_SRC directive is missing when specified in
// fromStringSpecCompliant"
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
for(var x in DEFAULTS) {
// each of these should be equivalent to DEFAULT_SRC
//DEFAULTS[x] + " does not use default rule."
do_check_true(cspr.permits("http://bar.com", DEFAULTS[x]));
}
});
test(
function test_CSPRep_fromStringSpecCompliant_oneDir() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_NEW;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC,
SD.FRAME_SRC, SD.CONNECT_SRC];
// check one-directive policies
cspr = CSPRep.fromStringSpecCompliant("default-src bar.com; script-src https://foo.com",
URI("http://self.com"));
for(var x in DEFAULTS) {
//DEFAULTS[x] + " does not use default rule."
do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule."
do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule."
do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule."
do_check_false(cspr.permits("https://foo.com", DEFAULTS[x]));
}
//"script-src false positive in policy.
do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC));
//"script-src false negative in policy.
do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC));
});
test(
function test_CSPRep_fromStringSpecCompliant_twodir() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_NEW;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC,
SD.CONNECT_SRC];
// check two-directive policies
var polstr = "default-src allow.com; " +
"script-src https://foo.com; " +
"img-src bar.com:*";
cspr = CSPRep.fromStringSpecCompliant(polstr, URI("http://self.com"));
for(var x in DEFAULTS) {
do_check_true(cspr.permits("http://allow.com", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule.
do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule.
do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule.
}
//"img-src does not use default rule.
do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC));
//"img-src does not use default rule.
do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
//"img-src does not use default rule.
do_check_true(cspr.permits("http://bar.com:88", SD.IMG_SRC));
//"script-src does not use default rule.
do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC));
//"script-src does not use default rule.
do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC));
//"script-src does not use default rule.
do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC));
});
test(function test_CSPRep_fromStringSpecCompliant_withself() {
var cspr;
var self = "https://self.com:34";
var SD = CSPRep.SRC_DIRECTIVES_NEW;
// check one-directive policies
cspr = CSPRep.fromStringSpecCompliant("default-src 'self'; script-src 'self' https://*:*",
URI(self));
cspr = CSPRep.fromString("default-src 'self'; script-src 'self' https://*:*",
URI(self));
//"img-src does not enforce default rule, 'self'.
do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
//"img-src does not allow self
@ -559,34 +435,10 @@ test(function test_CSPRep_fromStringSpecCompliant_withself() {
// (see bug 555068)
test(function test_FrameAncestor_defaults() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var self = "http://self.com:34";
var SD = CSPRep.SRC_DIRECTIVES;
cspr = CSPRep.fromString("allow 'none'", URI(self));
//"frame-ancestors should default to * not 'allow' value"
do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
cspr = CSPRep.fromString("allow 'none'; frame-ancestors 'self'", URI(self));
//"frame-ancestors should only allow self"
do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
});
test(function test_FrameAncestor_defaults_specCompliant() {
var cspr;
var self = "http://self.com:34";
var SD = CSPRep.SRC_DIRECTIVES_NEW;
cspr = CSPRep.fromStringSpecCompliant("default-src 'none'", URI(self));
cspr = CSPRep.fromString("default-src 'none'", URI(self));
//"frame-ancestors should default to * not 'default-src' value"
do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
@ -595,7 +447,7 @@ test(function test_FrameAncestor_defaults_specCompliant() {
do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
cspr = CSPRep.fromStringSpecCompliant("default-src 'none'; frame-ancestors 'self'", URI(self));
cspr = CSPRep.fromString("default-src 'none'; frame-ancestors 'self'", URI(self));
//"frame-ancestors should only allow self"
do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
@ -608,10 +460,10 @@ test(function test_FrameAncestor_defaults_specCompliant() {
test(function test_FrameAncestor_TLD_defaultPorts() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self"; //TLD only, no .com or anything.
cspr = CSPRep.fromString("allow 'self'; frame-ancestors 'self' http://foo:80 bar:80 http://three", URI(self));
cspr = CSPRep.fromString("default-src 'self'; frame-ancestors 'self' http://foo:80 bar:80 http://three", URI(self));
//"frame-ancestors should default to * not 'allow' value"
do_check_true(cspr.permits("http://self", SD.FRAME_ANCESTORS));
@ -630,7 +482,7 @@ test(function test_FrameAncestor_TLD_defaultPorts() {
test(function test_FrameAncestor_ignores_userpass_bug779918() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self.com/bar";
var testPolicy = "default-src 'self'; frame-ancestors 'self'";
@ -678,7 +530,7 @@ test(function test_FrameAncestor_ignores_userpass_bug779918() {
test(function test_CSP_ReportURI_parsing() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_NEW;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self.com:34";
var parsedURIs = [];
@ -692,48 +544,48 @@ test(function test_CSP_ReportURI_parsing() {
var uri_other_scheme_absolute = "https://self.com/report.py";
var uri_other_scheme_and_host_absolute = "https://foo.com/report.py";
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_absolute, URI(self));
cspr = CSPRep.fromString("default-src *; report-uri " + uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_absolute);
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_host_absolute, URI(self));
cspr = CSPRep.fromString("default-src *; report-uri " + uri_other_host_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_other_host_absolute);
do_check_eq(parsedURIs.length, 1); // the empty string is in there.
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_invalid_relative, URI(self));
cspr = CSPRep.fromString("default-src *; report-uri " + uri_invalid_relative, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, "");
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_relative, URI(self));
cspr = CSPRep.fromString("default-src *; report-uri " + uri_valid_relative, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_relative_expanded);
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_relative2, URI(self));
cspr = CSPRep.fromString("default-src *; report-uri " + uri_valid_relative2, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
dump(parsedURIs.length);
do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
do_check_eq(parsedURIs.length, 1);
// make sure cross-scheme reporting works
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_scheme_absolute, URI(self));
cspr = CSPRep.fromString("default-src *; report-uri " + uri_other_scheme_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
dump(parsedURIs.length);
do_check_in_array(parsedURIs, uri_other_scheme_absolute);
do_check_eq(parsedURIs.length, 1);
// make sure cross-scheme, cross-host reporting works
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_scheme_and_host_absolute, URI(self));
cspr = CSPRep.fromString("default-src *; report-uri " + uri_other_scheme_and_host_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
dump(parsedURIs.length);
do_check_in_array(parsedURIs, uri_other_scheme_and_host_absolute);
do_check_eq(parsedURIs.length, 1);
// combination!
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " +
cspr = CSPRep.fromString("default-src *; report-uri " +
uri_valid_relative2 + " " +
uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
@ -741,7 +593,7 @@ test(function test_CSP_ReportURI_parsing() {
do_check_in_array(parsedURIs, uri_valid_absolute);
do_check_eq(parsedURIs.length, 2);
cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " +
cspr = CSPRep.fromString("default-src *; report-uri " +
uri_valid_relative2 + " " +
uri_other_host_absolute + " " +
uri_valid_absolute, URI(self));
@ -755,32 +607,22 @@ test(function test_CSP_ReportURI_parsing() {
test(
function test_bug634778_duplicateDirective_Detection() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_OLD;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self.com:34";
var firstDomain = "http://first.com";
var secondDomain = "http://second.com";
var thirdDomain = "http://third.com";
// check for duplicate "default-src" directives
// Spec says first directive persists (subsequent re-statement is
// ignored)
cspr = CSPRep.fromString("default-src " + self + "; default-src " +
firstDomain, URI(self));
do_check_true(cspr.permits(self, SD.DEFAULT_SRC));
do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC));
// check for duplicate "allow" directives
cspr = CSPRep.fromString("allow " + self + "; allow " + firstDomain,
URI(self));
do_check_true(cspr.permits(self, SD.DEFAULT_SRC));
do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC));
// check for duplicate "allow" + "default-src" directives
cspr = CSPRep.fromString("allow " + self + "; default-src " + firstDomain,
URI(self));
do_check_true(cspr.permits(self, SD.DEFAULT_SRC));
do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC));
// check for duplicate report-uri directives
cspr = CSPRep.fromString("allow *; report-uri " + self + "/report.py; report-uri "
cspr = CSPRep.fromString("default-src *; report-uri " + self + "/report.py; report-uri "
+ firstDomain + "/report.py", URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, self + "/report.py");
@ -896,9 +738,7 @@ test(
test(
function test_bug764937_defaultSrcMissing() {
var cspObjSpecCompliant = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
var cspObjOld = Cc["@mozilla.org/contentsecuritypolicy;1"]
var cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
var selfURI = URI("http://self.com/");
@ -908,39 +748,21 @@ test(
};
const policy = "script-src 'self'";
cspObjSpecCompliant.appendPolicy(policy, selfURI, false, true);
cspObj.appendPolicy(policy, selfURI, false, 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,
do_check_true(testPermits(cspObj,
URI("http://bar.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
do_check_true(testPermits(cspObjSpecCompliant,
do_check_true(testPermits(cspObj,
URI("http://self.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
do_check_true(testPermits(cspObjSpecCompliant,
do_check_true(testPermits(cspObj,
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.appendPolicy(policy, selfURI, false, 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,
do_check_false(testPermits(cspObj,
URI("http://bar.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
@ -955,10 +777,10 @@ test(function test_equals_does_case_insensitive_comparison() {
// CSPSource equals ignores case
var upperCaseHost = "http://FOO.COM";
var lowerCaseHost = "http://foo.com";
src1 = CSPSource.fromString(lowerCaseHost);
src2 = CSPSource.fromString(lowerCaseHost);
var src1 = CSPSource.fromString(lowerCaseHost);
var src2 = CSPSource.fromString(lowerCaseHost);
do_check_true(src1.equals(src2))
src3 = CSPSource.fromString(upperCaseHost);
var src3 = CSPSource.fromString(upperCaseHost);
do_check_true(src1.equals(src3))
// CSPHost equals ignores case
@ -983,7 +805,7 @@ test(function test_equals_does_case_insensitive_comparison() {
test(function test_csp_permits_case_insensitive() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_NEW;
var SD = CSPRep.SRC_DIRECTIVES;
// checks directives can be case-insensitive
var selfHost = "http://self.com";
@ -1042,12 +864,15 @@ function run_test() {
httpServer.registerPathHandler("/policy", policyresponder);
for(let i in tests) {
tests[i]();
add_task(tests[i]);
}
//teardown
httpServer.stop(function() { });
do_test_finished();
do_register_cleanup(function () {
//teardown
httpServer.stop(function() { });
});
run_next_test();
}

View File

@ -21,7 +21,6 @@ support-files =
4_result_6.xml
[test_bug553888.js]
[test_bug558431.js]
[test_bug737966.js]
[test_csputils.js]
[test_cspreports.js]

View File

@ -1,2 +1,2 @@
Cache-Control: no-cache
X-Content-Security-Policy: allow 'self'
Content-Security-Policy: default-src 'self'

View File

@ -797,9 +797,6 @@ pref("dom.phonenumber.substringmatching.VE", 7);
// Support for the mozAudioChannel attribute on media elements is disabled in non-webapps
pref("media.useAudioChannelService", false);
// Turn on the CSP 1.0 parser for Content Security Policy headers
pref("security.csp.speccompliant", true);
// Enable hardware-accelerated Skia canvas
pref("gfx.canvas.azure.backends", "skia");
pref("gfx.canvas.azure.accelerated", true);