Bug 1279420 - Adding in security.csp.experimentalEnabled pref check to require-sri-for directive in CSP
MozReview-Commit-ID: 799ZZoW0YiG
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -1,15 +1,16 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ArrayUtils.h"
+#include "mozilla/Preferences.h"
#include "nsCOMPtr.h"
#include "nsCSPParser.h"
#include "nsCSPUtils.h"
#include "nsIConsoleService.h"
#include "nsIContentPolicy.h"
#include "nsIScriptError.h"
#include "nsIStringBundle.h"
#include "nsNetUtil.h"
@@ -115,16 +116,17 @@ nsCSPTokenizer::tokenizeCSPPolicy(const
nsCSPTokenizer tokenizer(aPolicyString.BeginReading(),
aPolicyString.EndReading());
tokenizer.generateTokens(outTokens);
}
/* ===== nsCSPParser ==================== */
+bool nsCSPParser::sCSPExperimentalEnabled = false;
nsCSPParser::nsCSPParser(cspTokens& aTokens,
nsIURI* aSelfURI,
nsCSPContext* aCSPContext,
bool aDeliveredViaMetaTag)
: mCurChar(nullptr)
, mEndChar(nullptr)
, mHasHashOrNonce(false)
@@ -132,16 +134,21 @@ nsCSPParser::nsCSPParser(cspTokens& aTok
, mChildSrc(nullptr)
, mFrameSrc(nullptr)
, mTokens(aTokens)
, mSelfURI(aSelfURI)
, mPolicy(nullptr)
, mCSPContext(aCSPContext)
, mDeliveredViaMetaTag(aDeliveredViaMetaTag)
{
+ static bool initialized = false;
+ if (!initialized) {
+ initialized = true;
+ Preferences::AddBoolVarCache(&sCSPExperimentalEnabled, "security.csp.experimentalEnabled");
+ }
CSPPARSERLOG(("nsCSPParser::nsCSPParser"));
}
nsCSPParser::~nsCSPParser()
{
CSPPARSERLOG(("nsCSPParser::~nsCSPParser"));
}
@@ -1002,37 +1009,32 @@ nsCSPParser::directiveValue(nsTArray<nsC
// special case handling of the referrer directive (since it doesn't contain
// source lists)
if (CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::REFERRER_DIRECTIVE)) {
referrerDirectiveValue();
return;
}
- // special case handling of the require-sri-for directive (since it doesn't
- // contain a source lists but rather types, e.g., style or script)
- if (CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::REQUIRE_SRI_FOR)) {
- // handled in directive()
- return;
- }
-
// Otherwise just forward to sourceList
sourceList(outSrcs);
}
// directive-name = 1*( ALPHA / DIGIT / "-" )
nsCSPDirective*
nsCSPParser::directiveName()
{
CSPPARSERLOG(("nsCSPParser::directiveName, mCurToken: %s, mCurValue: %s",
NS_ConvertUTF16toUTF8(mCurToken).get(),
NS_ConvertUTF16toUTF8(mCurValue).get()));
// Check if it is a valid directive
- if (!CSP_IsValidDirective(mCurToken)) {
+ if (!CSP_IsValidDirective(mCurToken) ||
+ (!sCSPExperimentalEnabled &&
+ CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::REQUIRE_SRI_FOR))) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldNotProcessUnknownDirective",
params, ArrayLength(params));
return nullptr;
}
// The directive 'reflected-xss' is part of CSP 1.1, see:
// http://www.w3.org/TR/2014/WD-CSP11-20140211/#reflected-xss
--- a/dom/security/nsCSPParser.h
+++ b/dom/security/nsCSPParser.h
@@ -106,16 +106,18 @@ class nsCSPParser {
bool aDeliveredViaMetaTag);
private:
nsCSPParser(cspTokens& aTokens,
nsIURI* aSelfURI,
nsCSPContext* aCSPContext,
bool aDeliveredViaMetaTag);
+ static bool sCSPExperimentalEnabled;
+
~nsCSPParser();
// Parsing the CSP using the source-list from http://www.w3.org/TR/CSP11/#source-list
nsCSPPolicy* policy();
void directive();
nsCSPDirective* directiveName();
void directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs);
--- a/dom/security/test/TestCSPParser.cpp
+++ b/dom/security/test/TestCSPParser.cpp
@@ -23,16 +23,18 @@ class nsXPIDLString;
template<class T> class nsReadingIterator;
#endif
#include "nsIContentSecurityPolicy.h"
#include "nsNetUtil.h"
#include "TestHarness.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/dom/nsCSPContext.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
#ifndef MOZILLA_INTERNAL_API
#undef nsString_h___
#undef nsAString_h___
#undef nsReadableUtils_h___
#endif
/*
@@ -161,20 +163,33 @@ nsresult runTest(uint32_t aExpectedPolic
}
// ============================= run Tests ========================
nsresult runTestSuite(const PolicyTest* aPolicies,
uint32_t aPolicyCount,
uint32_t aExpectedPolicyCount) {
nsresult rv;
+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+ bool experimentalEnabledCache = false;
+ if (prefs)
+ {
+ prefs->GetBoolPref("security.csp.experimentalEnabled", &experimentalEnabledCache);
+ prefs->SetBoolPref("security.csp.experimentalEnabled", true);
+ }
+
for (uint32_t i = 0; i < aPolicyCount; i++) {
rv = runTest(aExpectedPolicyCount, aPolicies[i].policy, aPolicies[i].expectedResult);
NS_ENSURE_SUCCESS(rv, rv);
}
+
+ if (prefs) {
+ prefs->SetBoolPref("security.csp.experimentalEnabled", experimentalEnabledCache);
+ }
+
return NS_OK;
}
// ============================= TestDirectives ========================
nsresult TestDirectives() {
static const PolicyTest policies[] =
--- a/dom/security/test/sri/mochitest.ini
+++ b/dom/security/test/sri/mochitest.ini
@@ -32,8 +32,9 @@ support-files =
style_301.css^headers^
[test_script_sameorigin.html]
[test_script_crossdomain.html]
[test_sri_disabled.html]
[test_style_crossdomain.html]
[test_style_sameorigin.html]
[test_require-sri-for_csp_directive.html]
+[test_require-sri-for_csp_directive_disabled.html]
--- a/dom/security/test/sri/test_require-sri-for_csp_directive.html
+++ b/dom/security/test/sri/test_require-sri-for_csp_directive.html
@@ -9,36 +9,38 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265318">Mozilla Bug 1265318</a>
<iframe style="width:200px;height:200px;" id="test_frame"></iframe>
</body>
<script type="application/javascript">
+ SpecialPowers.setBoolPref("security.csp.experimentalEnabled", true);
SimpleTest.waitForExplicitFinish();
function handler(event) {
switch (event.data) {
case 'good_sriLoaded':
ok(true, "Eligible SRI resources was correctly loaded.");
break;
case 'bad_nonsriLoaded':
ok(false, "Eligible non-SRI resource should be blocked by the CSP!");
break;
case 'good_nonsriBlocked':
ok(true, "Eligible non-SRI resources was correctly blocked by the CSP.");
break;
case 'finish':
var blackText = frame.contentDocument.getElementById('black-text');
var blackTextColor = frame.contentWindow.getComputedStyle(blackText, null).getPropertyValue('color');
- ok(blackTextColor == 'rgb(0, 0, 0)', "The second part should still be black.");
+ ok(blackTextColor == 'rgb(0, 0, 0)', "The second part should not be black.");
removeEventListener('message', handler);
SimpleTest.finish();
break;
default:
+ ok(false, 'Something is wrong here');
break;
}
}
addEventListener("message", handler);
var frame = document.getElementById("test_frame");
frame.src = "iframe_require-sri-for_main.html";
</script>
</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/test_require-sri-for_csp_directive_disabled.html
@@ -0,0 +1,46 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for diabled SRI require-sri-for CSP directive</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265318">Mozilla Bug 1265318</a>
+<iframe style="width:200px;height:200px;" id="test_frame"></iframe>
+</body>
+<script type="application/javascript">
+ SpecialPowers.setBoolPref("security.csp.experimentalEnabled", false);
+ SimpleTest.waitForExplicitFinish();
+ function handler(event) {
+ switch (event.data) {
+ case 'good_sriLoaded':
+ ok(true, "Eligible SRI resources was correctly loaded.");
+ break;
+ case 'bad_nonsriLoaded':
+ ok(true, "Eligible non-SRI resource should be blocked by the CSP!");
+ break;
+ case 'good_nonsriBlocked':
+ ok(false, "Eligible non-SRI resources was correctly blocked by the CSP.");
+ break;
+ case 'finish':
+ var blackText = frame.contentDocument.getElementById('black-text');
+ var blackTextColor = frame.contentWindow.getComputedStyle(blackText, null).getPropertyValue('color');
+ ok(blackTextColor != 'rgb(0, 0, 0)', "The second part should still be black.");
+ removeEventListener('message', handler);
+ SimpleTest.finish();
+ break;
+ default:
+ ok(false, 'Something is wrong here');
+ break;
+ }
+ }
+ addEventListener("message", handler);
+ var frame = document.getElementById("test_frame");
+ frame.src = "iframe_require-sri-for_main.html";
+</script>
+</html>