mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
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:
parent
b7e7fb40b8
commit
b34ba073a6
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -1 +1 @@
|
||||
X-Content-Security-Policy: default-src 'self'
|
||||
Content-Security-Policy: default-src 'self'
|
||||
|
@ -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;
|
||||
},
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
TEST_TOOL_DIRS += [
|
||||
'csp',
|
||||
'xcsp',
|
||||
'websocket_hybi',
|
||||
]
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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]
|
||||
|
@ -1,2 +1,2 @@
|
||||
Cache-Control: no-cache
|
||||
X-Content-Security-Policy: allow 'self'
|
||||
Content-Security-Policy: default-src 'self'
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user