Commit f1933561 authored by rob's avatar rob Committed by Commit bot

Ignore insecure parts of CSP in extensions and allow extension to load

Previously, insecure CSP directive values caused refusal of Chrome to
load the Chrome extension. Now, insecure values are stripped from the
CSP, and a list of detailed warnings is printed at the extensions page.

Renamed ContentSecurityPolicyIsSecure to SanitizeContentSecurityPolicy
and let it return a string (the sanitized CSP) instead of a boolean
that tells whether the CSP was considered secure.

BUG=434773
R=kalman@chromium.org
R=mkwst@chromium.org
TEST=extensions_unittests=ExtensionCSPValidator.*
     unit_tests=ContentSecurityPolicyManifestTest.*:PlatformAppsManifestTest:PlatformAppContentSecurityPolicy

Review URL: https://codereview.chromium.org/747403002

Cr-Commit-Position: refs/heads/master@{#310191}
parent 1531d38e
......@@ -3,22 +3,27 @@
// found in the LICENSE file.
#include "chrome/common/extensions/manifest_tests/chrome_manifest_test.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/manifest_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace errors = extensions::manifest_errors;
using extensions::ErrorUtils;
class ContentSecurityPolicyManifestTest : public ChromeManifestTest {
};
TEST_F(ContentSecurityPolicyManifestTest, InsecureContentSecurityPolicy) {
Testcase testcases[] = {
Testcase("insecure_contentsecuritypolicy_1.json",
errors::kInsecureContentSecurityPolicy),
Testcase(
"insecure_contentsecuritypolicy_1.json",
ErrorUtils::FormatErrorMessage(errors::kInvalidCSPInsecureValue,
"http://example.com", "script-src")),
Testcase("insecure_contentsecuritypolicy_2.json",
errors::kInsecureContentSecurityPolicy),
ErrorUtils::FormatErrorMessage(errors::kInvalidCSPInsecureValue,
"'unsafe-inline'", "script-src")),
Testcase("insecure_contentsecuritypolicy_3.json",
errors::kInsecureContentSecurityPolicy),
};
RunTestcases(testcases, arraysize(testcases), EXPECT_TYPE_ERROR);
ErrorUtils::FormatErrorMessage(
errors::kInvalidCSPMissingSecureSrc, "object-src"))};
RunTestcases(testcases, arraysize(testcases), EXPECT_TYPE_WARNING);
}
......@@ -89,14 +89,15 @@ TEST_F(PlatformAppsManifestTest, PlatformAppContentSecurityPolicy) {
EXPECT_EQ(0U, extension->install_warnings().size())
<< "Unexpected warning " << extension->install_warnings()[0].message;
EXPECT_TRUE(extension->is_platform_app());
EXPECT_EQ("default-src 'self' https://www.google.com",
EXPECT_EQ("default-src 'self' https://www.google.com;",
CSPInfo::GetResourceContentSecurityPolicy(extension.get(),
std::string()));
// But even whitelisted ones must specify a secure policy.
LoadAndExpectError(
LoadAndExpectWarning(
"init_platform_app_csp_insecure.json",
errors::kInsecureContentSecurityPolicy);
ErrorUtils::FormatErrorMessage(errors::kInvalidCSPInsecureValue,
"http://www.google.com", "default-src"));
}
TEST_F(PlatformAppsManifestTest, CertainApisRequirePlatformApps) {
......
......@@ -37,7 +37,7 @@ TEST_F(SandboxedPagesManifestTest, SandboxedPages) {
const char kSandboxedCSP[] = "sandbox allow-scripts allow-forms allow-popups";
const char kDefaultCSP[] =
"script-src 'self' chrome-extension-resource:; object-src 'self'";
"script-src 'self' chrome-extension-resource:; object-src 'self';";
const char kCustomSandboxedCSP[] =
"sandbox; script-src: https://www.google.com";
......
......@@ -11,6 +11,9 @@
#include "base/strings/string_util.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/constants.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest_constants.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
namespace extensions {
......@@ -24,6 +27,10 @@ const char kScriptSrc[] = "script-src";
const char kObjectSrc[] = "object-src";
const char kPluginTypes[] = "plugin-types";
const char kObjectSrcDefaultDirective[] = "object-src 'self';";
const char kScriptSrcDefaultDirective[] =
"script-src 'self' chrome-extension-resource:;";
const char kSandboxDirectiveName[] = "sandbox";
const char kAllowSameOriginToken[] = "allow-same-origin";
const char kAllowTopNavigation[] = "allow-top-navigation";
......@@ -38,14 +45,10 @@ const char* const kSandboxedPluginTypes[] = {
struct DirectiveStatus {
explicit DirectiveStatus(const char* name)
: directive_name(name)
, seen_in_policy(false)
, is_secure(false) {
}
: directive_name(name), seen_in_policy(false) {}
const char* directive_name;
bool seen_in_policy;
bool is_secure;
};
// Returns whether |url| starts with |scheme_and_separator| and does not have a
......@@ -63,12 +66,6 @@ bool isNonWildcardTLD(const std::string& url,
if (end_of_host == std::string::npos)
end_of_host = url.size();
// A missing host such as "chrome-extension://" is invalid, but for backwards-
// compatibility, accept such CSP parts. They will be ignored by Blink anyway.
// TODO(robwu): Remove this special case once crbug.com/434773 is fixed.
if (start_of_host == end_of_host)
return true;
// Note: It is sufficient to only compare the first character against '*'
// because the CSP only allows wildcards at the start of a directive, see
// host-source and host-part at http://www.w3.org/TR/CSP2/#source-list-syntax
......@@ -115,11 +112,20 @@ bool isNonWildcardTLD(const std::string& url,
return registry_length != 0;
}
bool HasOnlySecureTokens(base::StringTokenizer& tokenizer,
int options) {
while (tokenizer.GetNext()) {
std::string source = tokenizer.token();
InstallWarning CSPInstallWarning(const std::string& csp_warning) {
return InstallWarning(csp_warning, manifest_keys::kContentSecurityPolicy);
}
void GetSecureDirectiveValues(const std::string& directive_name,
base::StringTokenizer* tokenizer,
int options,
std::vector<std::string>* sane_csp_parts,
std::vector<InstallWarning>* warnings) {
sane_csp_parts->push_back(directive_name);
while (tokenizer->GetNext()) {
std::string source = tokenizer->token();
base::StringToLowerASCII(&source);
bool is_secure_csp_token = false;
// We might need to relax this whitelist over time.
if (source == "'self'" ||
......@@ -137,52 +143,45 @@ bool HasOnlySecureTokens(base::StringTokenizer& tokenizer,
url::kStandardSchemeSeparator,
false) ||
StartsWithASCII(source, "chrome-extension-resource:", true)) {
continue;
is_secure_csp_token = true;
} else if ((options & OPTIONS_ALLOW_UNSAFE_EVAL) &&
source == "'unsafe-eval'") {
is_secure_csp_token = true;
}
if (options & OPTIONS_ALLOW_UNSAFE_EVAL) {
if (source == "'unsafe-eval'")
continue;
if (is_secure_csp_token) {
sane_csp_parts->push_back(source);
} else if (warnings) {
warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage(
manifest_errors::kInvalidCSPInsecureValue, source, directive_name)));
}
return false;
}
return true; // Empty values default to 'none', which is secure.
// End of CSP directive that was started at the beginning of this method. If
// none of the values are secure, the policy will be empty and default to
// 'none', which is secure.
sane_csp_parts->back().push_back(';');
}
// Returns true if |directive_name| matches |status.directive_name|.
bool UpdateStatus(const std::string& directive_name,
base::StringTokenizer& tokenizer,
base::StringTokenizer* tokenizer,
DirectiveStatus* status,
int options) {
if (status->seen_in_policy)
return false;
int options,
std::vector<std::string>* sane_csp_parts,
std::vector<InstallWarning>* warnings) {
if (directive_name != status->directive_name)
return false;
status->seen_in_policy = true;
status->is_secure = HasOnlySecureTokens(tokenizer, options);
return true;
}
// Parses the plugin-types directive and returns the list of mime types
// specified in |plugin_types|.
bool ParsePluginTypes(const std::string& directive_name,
base::StringTokenizer& tokenizer,
std::vector<std::string>* plugin_types) {
DCHECK(plugin_types);
if (directive_name != kPluginTypes || !plugin_types->empty())
return false;
while (tokenizer.GetNext()) {
std::string mime_type = tokenizer.token();
base::StringToLowerASCII(&mime_type);
// Since we're comparing the mime types to a whitelist, we don't check them
// for strict validity right now.
plugin_types->push_back(mime_type);
if (!status->seen_in_policy) {
status->seen_in_policy = true;
GetSecureDirectiveValues(directive_name, tokenizer, options, sane_csp_parts,
warnings);
} else {
// Don't show any errors for duplicate CSP directives, because it will be
// ignored by the CSP parser (http://www.w3.org/TR/CSP2/#policy-parsing).
GetSecureDirectiveValues(directive_name, tokenizer, options, sane_csp_parts,
NULL);
}
return true;
}
......@@ -201,20 +200,26 @@ bool PluginTypeAllowed(const std::string& plugin_type) {
// the set specified in kSandboxedPluginTypes.
bool AllowedToHaveInsecureObjectSrc(
int options,
const std::vector<std::string>& plugin_types) {
const std::vector<std::string>& directives) {
if (!(options & OPTIONS_ALLOW_INSECURE_OBJECT_SRC))
return false;
// plugin-types must be specified.
if (plugin_types.empty())
return false;
for (const auto& plugin_type : plugin_types) {
if (!PluginTypeAllowed(plugin_type))
for (size_t i = 0; i < directives.size(); ++i) {
const std::string& input = directives[i];
base::StringTokenizer tokenizer(input, " \t\r\n");
if (!tokenizer.GetNext())
continue;
if (!LowerCaseEqualsASCII(tokenizer.token(), kPluginTypes))
continue;
while (tokenizer.GetNext()) {
if (!PluginTypeAllowed(tokenizer.token()))
return false;
}
// All listed plugin types are whitelisted.
return true;
}
// plugin-types not specified.
return false;
}
} // namespace
......@@ -228,8 +233,10 @@ bool ContentSecurityPolicyIsLegal(const std::string& policy) {
std::string::npos;
}
bool ContentSecurityPolicyIsSecure(const std::string& policy,
int options) {
std::string SanitizeContentSecurityPolicy(
const std::string& policy,
int options,
std::vector<InstallWarning>* warnings) {
// See http://www.w3.org/TR/CSP/#parse-a-csp-policy for parsing algorithm.
std::vector<std::string> directives;
base::SplitString(policy, ';', &directives);
......@@ -238,8 +245,11 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy,
DirectiveStatus script_src_status(kScriptSrc);
DirectiveStatus object_src_status(kObjectSrc);
std::vector<std::string> plugin_types;
bool allow_insecure_object_src =
AllowedToHaveInsecureObjectSrc(options, directives);
std::vector<std::string> sane_csp_parts;
std::vector<InstallWarning> default_src_csp_warnings;
for (size_t i = 0; i < directives.size(); ++i) {
std::string& input = directives[i];
base::StringTokenizer tokenizer(input, " \t\r\n");
......@@ -249,33 +259,47 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy,
std::string directive_name = tokenizer.token();
base::StringToLowerASCII(&directive_name);
if (UpdateStatus(directive_name, tokenizer, &default_src_status, options))
if (UpdateStatus(directive_name, &tokenizer, &default_src_status, options,
&sane_csp_parts, &default_src_csp_warnings))
continue;
if (UpdateStatus(directive_name, tokenizer, &script_src_status, options))
if (UpdateStatus(directive_name, &tokenizer, &script_src_status, options,
&sane_csp_parts, warnings))
continue;
if (UpdateStatus(directive_name, tokenizer, &object_src_status, options))
if (!allow_insecure_object_src &&
UpdateStatus(directive_name, &tokenizer, &object_src_status, options,
&sane_csp_parts, warnings))
continue;
if (ParsePluginTypes(directive_name, tokenizer, &plugin_types))
continue;
}
if (script_src_status.seen_in_policy && !script_src_status.is_secure)
return false;
if (object_src_status.seen_in_policy && !object_src_status.is_secure) {
// Note that this does not fully check the object-src source list for
// validity but Blink will do this anyway.
if (!AllowedToHaveInsecureObjectSrc(options, plugin_types))
return false;
// Pass the other CSP directives as-is without further validation.
sane_csp_parts.push_back(input + ";");
}
if (default_src_status.seen_in_policy && !default_src_status.is_secure) {
return script_src_status.seen_in_policy &&
object_src_status.seen_in_policy;
if (default_src_status.seen_in_policy) {
if (!script_src_status.seen_in_policy ||
!object_src_status.seen_in_policy) {
// Insecure values in default-src are only relevant if either script-src
// or object-src is omitted.
if (warnings)
warnings->insert(warnings->end(),
default_src_csp_warnings.begin(),
default_src_csp_warnings.end());
}
} else {
if (!script_src_status.seen_in_policy) {
sane_csp_parts.push_back(kScriptSrcDefaultDirective);
if (warnings)
warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage(
manifest_errors::kInvalidCSPMissingSecureSrc, kScriptSrc)));
}
if (!object_src_status.seen_in_policy && !allow_insecure_object_src) {
sane_csp_parts.push_back(kObjectSrcDefaultDirective);
if (warnings)
warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage(
manifest_errors::kInvalidCSPMissingSecureSrc, kObjectSrc)));
}
}
return default_src_status.seen_in_policy ||
(script_src_status.seen_in_policy && object_src_status.seen_in_policy);
return JoinString(sane_csp_parts, ' ');
}
bool ContentSecurityPolicyIsSandboxed(
......
......@@ -43,8 +43,13 @@ enum Options {
// case for extensions. Platform apps disallow it.
//
// |options| is a bitmask of Options.
bool ContentSecurityPolicyIsSecure(
const std::string& policy, int options);
//
// If |warnings| is not NULL, any validation errors are appended to |warnings|.
// Returns the sanitized policy.
std::string SanitizeContentSecurityPolicy(
const std::string& policy,
int options,
std::vector<InstallWarning>* warnings);
// Checks whether the given |policy| enforces a unique origin sandbox as
// defined by http://www.whatwg.org/specs/web-apps/current-work/multipage/
......
......@@ -3,16 +3,112 @@
// found in the LICENSE file.
#include "extensions/common/csp_validator.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
using extensions::csp_validator::ContentSecurityPolicyIsLegal;
using extensions::csp_validator::ContentSecurityPolicyIsSecure;
using extensions::csp_validator::SanitizeContentSecurityPolicy;
using extensions::csp_validator::ContentSecurityPolicyIsSandboxed;
using extensions::csp_validator::OPTIONS_NONE;
using extensions::csp_validator::OPTIONS_ALLOW_UNSAFE_EVAL;
using extensions::csp_validator::OPTIONS_ALLOW_INSECURE_OBJECT_SRC;
using extensions::ErrorUtils;
using extensions::InstallWarning;
using extensions::Manifest;
namespace {
std::string InsecureValueWarning(const std::string& directive,
const std::string& value) {
return ErrorUtils::FormatErrorMessage(
extensions::manifest_errors::kInvalidCSPInsecureValue, value, directive);
}
std::string MissingSecureSrcWarning(const std::string& directive) {
return ErrorUtils::FormatErrorMessage(
extensions::manifest_errors::kInvalidCSPMissingSecureSrc, directive);
}
testing::AssertionResult CheckSanitizeCSP(
const std::string& policy,
int options,
const std::string& expected_csp,
const std::vector<std::string>& expected_warnings) {
std::vector<InstallWarning> actual_warnings;
std::string actual_csp = SanitizeContentSecurityPolicy(policy,
options,
&actual_warnings);
if (actual_csp != expected_csp)
return testing::AssertionFailure()
<< "SanitizeContentSecurityPolicy returned an unexpected CSP.\n"
<< "Expected CSP: " << expected_csp << "\n"
<< " Actual CSP: " << actual_csp;
if (expected_warnings.size() != actual_warnings.size()) {
testing::Message msg;
msg << "Expected " << expected_warnings.size()
<< " warnings, but got " << actual_warnings.size();
for (size_t i = 0; i < actual_warnings.size(); ++i)
msg << "\nWarning " << i << " " << actual_warnings[i].message;
return testing::AssertionFailure() << msg;
}
for (size_t i = 0; i < expected_warnings.size(); ++i) {
if (expected_warnings[i] != actual_warnings[i].message)
return testing::AssertionFailure()
<< "Unexpected warning from SanitizeContentSecurityPolicy.\n"
<< "Expected warning[" << i << "]: " << expected_warnings[i]
<< " Actual warning[" << i << "]: " << actual_warnings[i].message;
}
return testing::AssertionSuccess();
}
testing::AssertionResult CheckSanitizeCSP(const std::string& policy,
int options) {
return CheckSanitizeCSP(policy, options, policy, std::vector<std::string>());
}
testing::AssertionResult CheckSanitizeCSP(const std::string& policy,
int options,
const std::string& expected_csp) {
std::vector<std::string> expected_warnings;
return CheckSanitizeCSP(policy, options, expected_csp, expected_warnings);
}
testing::AssertionResult CheckSanitizeCSP(const std::string& policy,
int options,
const std::string& expected_csp,
const std::string& warning1) {
std::vector<std::string> expected_warnings(1, warning1);
return CheckSanitizeCSP(policy, options, expected_csp, expected_warnings);
}
testing::AssertionResult CheckSanitizeCSP(const std::string& policy,
int options,
const std::string& expected_csp,
const std::string& warning1,
const std::string& warning2) {
std::vector<std::string> expected_warnings(1, warning1);
expected_warnings.push_back(warning2);
return CheckSanitizeCSP(policy, options, expected_csp, expected_warnings);
}
testing::AssertionResult CheckSanitizeCSP(const std::string& policy,
int options,
const std::string& expected_csp,
const std::string& warning1,
const std::string& warning2,
const std::string& warning3) {
std::vector<std::string> expected_warnings(1, warning1);
expected_warnings.push_back(warning2);
expected_warnings.push_back(warning3);
return CheckSanitizeCSP(policy, options, expected_csp, expected_warnings);
}
}; // namespace
TEST(ExtensionCSPValidator, IsLegal) {
EXPECT_TRUE(ContentSecurityPolicyIsLegal("foo"));
EXPECT_TRUE(ContentSecurityPolicyIsLegal(
......@@ -26,188 +122,277 @@ TEST(ExtensionCSPValidator, IsLegal) {
}
TEST(ExtensionCSPValidator, IsSecure) {
EXPECT_FALSE(
ContentSecurityPolicyIsSecure(std::string(), OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure("img-src https://google.com",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
std::string(), OPTIONS_ALLOW_UNSAFE_EVAL,
"script-src 'self' chrome-extension-resource:; object-src 'self';",
MissingSecureSrcWarning("script-src"),
MissingSecureSrcWarning("object-src")));
EXPECT_TRUE(CheckSanitizeCSP(
"img-src https://google.com", OPTIONS_ALLOW_UNSAFE_EVAL,
"img-src https://google.com; script-src 'self'"
" chrome-extension-resource:; object-src 'self';",
MissingSecureSrcWarning("script-src"),
MissingSecureSrcWarning("object-src")));
EXPECT_TRUE(CheckSanitizeCSP(
"script-src a b", OPTIONS_ALLOW_UNSAFE_EVAL,
"script-src; object-src 'self';",
InsecureValueWarning("script-src", "a"),
InsecureValueWarning("script-src", "b"),
MissingSecureSrcWarning("object-src")));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src *", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'none'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' ftp://google.com", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://google.com", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src *; default-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self'; default-src *", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self'; default-src *; script-src *; script-src 'self'",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self'; default-src *; script-src 'self'; script-src *",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src *", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src;",
InsecureValueWarning("default-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self';", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'none';", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' ftp://google.com", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "ftp://google.com")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://google.com;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src *; script-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
EXPECT_TRUE(CheckSanitizeCSP(
"default-src *; default-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src; default-src 'self';",
InsecureValueWarning("default-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self'; default-src *;", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self'; default-src;"));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self'; default-src *; script-src *; script-src 'self'",
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self'; default-src; script-src; script-src 'self';",
InsecureValueWarning("script-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self'; default-src *; script-src 'self'; script-src *;",
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self'; default-src; script-src 'self'; script-src;"));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src *; script-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src; script-src 'self';",
InsecureValueWarning("default-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src *; script-src 'self'; img-src 'self'",
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src; script-src 'self'; img-src 'self';",
InsecureValueWarning("default-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src *; script-src 'self'; object-src 'self';",
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src; script-src 'self'; object-src 'self';"));
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src 'self';", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'unsafe-eval';", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'unsafe-eval'", OPTIONS_NONE,
"default-src;",
InsecureValueWarning("default-src", "'unsafe-eval'")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'unsafe-inline'", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src;",
InsecureValueWarning("default-src", "'unsafe-inline'")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'unsafe-inline' 'none'", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'none';",
InsecureValueWarning("default-src", "'unsafe-inline'")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://google.com", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "http://google.com")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://google.com;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' chrome://resources;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' chrome-extension://aabbcc;",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src *; script-src 'self'; object-src 'self'",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"script-src 'self'; object-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'unsafe-eval'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'unsafe-eval'", OPTIONS_NONE));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'unsafe-inline'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'unsafe-inline' 'none'", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' http://google.com", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://google.com", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' chrome://resources", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' chrome-extension://aabbcc",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' chrome-extension-resource://aabbcc",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https:", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' http:", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' google.com", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' *", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' *:*", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' *:*/", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' *:*/path", OPTIONS_ALLOW_UNSAFE_EVAL));
// "https://" is an invalid CSP, so it will be ignored by Blink.
// TODO(robwu): Change to EXPECT_FALSE once http://crbug.com/434773 is fixed.
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*:*", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*:*/", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*:*/path", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.com", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.*.google.com/", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.*.google.com:*/",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://www.*.google.com/",
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' chrome-extension-resource://aabbcc;",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https:", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https:")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http:", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "http:")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' google.com", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "google.com")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' *", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' *:*", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "*:*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' *:*/", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "*:*/")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' *:*/path", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "*:*/path")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*:*", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://*:*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*:*/", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://*:*/")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*:*/path", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://*:*/path")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.com", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://*.com")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.*.google.com/", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://*.*.google.com/")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.*.google.com:*/", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://*.*.google.com:*/")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://www.*.google.com/", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://www.*.google.com/")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://www.*.google.com:*/",
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "https://www.*.google.com:*/")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' chrome://*", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "chrome://*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' chrome-extension://*", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "chrome-extension://*")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' chrome-extension://", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "chrome-extension://")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.google.com;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.google.com:1;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.google.com:*;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.google.com:1/;",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' chrome://*", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' chrome-extension://*", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.google.com", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.google.com:1", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.google.com:*", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.google.com:1/", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.google.com:*/", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' http://127.0.0.1", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' http://localhost", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' http://lOcAlHoSt", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' http://127.0.0.1:9999", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' http://localhost:8888", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' http://127.0.0.1.example.com",
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.google.com:*/;",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://127.0.0.1;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://localhost;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://lOcAlHoSt;", OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self' http://localhost;"));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://127.0.0.1:9999;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://localhost:8888;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://127.0.0.1.example.com",
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "http://127.0.0.1.example.com")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' http://localhost.example.com",
OPTIONS_ALLOW_UNSAFE_EVAL));
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "http://localhost.example.com")));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' blob:", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' blob:;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' blob:http://example.com/XXX",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' filesystem:", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"default-src 'self' filesystem:http://example.com/XXX",
OPTIONS_ALLOW_UNSAFE_EVAL));
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "blob:http://example.com/xxx")));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' filesystem:;", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' filesystem:http://example.com/XX",
OPTIONS_ALLOW_UNSAFE_EVAL,
"default-src 'self';",
InsecureValueWarning("default-src", "filesystem:http://example.com/xx")));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://*.googleapis.com",
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://*.googleapis.com;",
OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' https://x.googleapis.com",
EXPECT_TRUE(CheckSanitizeCSP(
"default-src 'self' https://x.googleapis.com;",
OPTIONS_ALLOW_UNSAFE_EVAL));
// "chrome-extension://" is an invalid CSP and ignored by Blink, but extension
// authors have been using this string anyway, so we cannot refuse this string
// until extensions can be loaded with an invalid CSP. http://crbug.com/434773
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"default-src 'self' chrome-extension://", OPTIONS_ALLOW_UNSAFE_EVAL));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"script-src 'self'; object-src *", OPTIONS_NONE));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"script-src 'self'; object-src *", OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"script-src 'self'; object-src *; plugin-types application/pdf",
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src *", OPTIONS_NONE,
"script-src 'self'; object-src;",
InsecureValueWarning("object-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src *", OPTIONS_ALLOW_INSECURE_OBJECT_SRC,
"script-src 'self'; object-src;",
InsecureValueWarning("object-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src *; plugin-types application/pdf;",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src *; "
"plugin-types application/x-shockwave-flash",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
OPTIONS_ALLOW_INSECURE_OBJECT_SRC,
"script-src 'self'; object-src; "
"plugin-types application/x-shockwave-flash;",
InsecureValueWarning("object-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src *; "
"plugin-types application/x-shockwave-flash application/pdf",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
"plugin-types application/x-shockwave-flash application/pdf;",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC,
"script-src 'self'; object-src; "
"plugin-types application/x-shockwave-flash application/pdf;",
InsecureValueWarning("object-src", "*")));
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src http://www.example.com; "
"plugin-types application/pdf",
"plugin-types application/pdf;",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
EXPECT_TRUE(CheckSanitizeCSP(
"object-src http://www.example.com blob:; script-src 'self'; "
"plugin-types application/pdf",
"plugin-types application/pdf;",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_TRUE(ContentSecurityPolicyIsSecure(
EXPECT_TRUE(CheckSanitizeCSP(
"script-src 'self'; object-src http://*.example.com; "
"plugin-types application/pdf",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_FALSE(ContentSecurityPolicyIsSecure(
"script-src *; object-src *; plugin-types application/pdf",
"plugin-types application/pdf;",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
EXPECT_TRUE(CheckSanitizeCSP(
"script-src *; object-src *; plugin-types application/pdf;",
OPTIONS_ALLOW_INSECURE_OBJECT_SRC,
"script-src; object-src *; plugin-types application/pdf;",
InsecureValueWarning("script-src", "*")));
}
TEST(ExtensionCSPValidator, IsSandboxed) {
......
......@@ -314,10 +314,15 @@ const char kInvalidContentPackSites[] =
"Invalid value for Content Pack sites - files must be strings.";
const char kInvalidContentScript[] =
"Invalid value for 'content_scripts[*]'.";
const char kInvalidContentSecurityPolicy[] =
"Invalid value for 'content_security_policy'.";
const char kInvalidContentScriptsList[] =
"Invalid value for 'content_scripts'.";
const char kInvalidContentSecurityPolicy[] =
"Invalid value for 'content_security_policy'.";
const char kInvalidCSPInsecureValue[] =
"Ignored insecure CSP value \"*\" in directive '*'.";
const char kInvalidCSPMissingSecureSrc[] =
"CSP directive '*' must be specified (either explicitly, or implicitly via"
" 'default-src') and must whitelist only secure resources.";
const char kInvalidCss[] =
"Invalid value for 'content_scripts[*].css[*]'.";
const char kInvalidCssList[] =
......@@ -627,14 +632,6 @@ const char kInvalidWebURLs[] =
"Invalid value for 'app.urls'.";
const char kInvalidZipHash[] =
"Required key 'zip_hash' is missing or invalid.";
const char kInsecureContentSecurityPolicy[] =
"Invalid value for 'content_security_policy': Both 'script-src' and"
" 'object-src' directives must be specified (either explicitly, or"
" implicitly via 'default-src'), and both must whitelist only secure"
" resources. You may include any of the following sources: \"'self'\","
" \"'unsafe-eval'\", \"http://127.0.0.1\", \"http://localhost\", or any"
" \"https://\" or \"chrome-extension://\" origin. For more information,"
" see http://developer.chrome.com/extensions/contentSecurityPolicy.html";
const char kKeyIsDeprecatedWithReplacement[] =
"Key \"*\" is deprecated. Key \"*\" should be used instead.";
const char kLauncherPagePageRequired[] =
......
......@@ -279,6 +279,8 @@ extern const char kInvalidContentPackSites[];
extern const char kInvalidContentScript[];
extern const char kInvalidContentScriptsList[];
extern const char kInvalidContentSecurityPolicy[];
extern const char kInvalidCSPInsecureValue[];
extern const char kInvalidCSPMissingSecureSrc[];
extern const char kInvalidCss[];
extern const char kInvalidCssList[];
extern const char kInvalidDefaultLocale[];
......
......@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "extensions/common/csp_validator.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/sandboxed_page_info.h"
......@@ -18,12 +19,12 @@ namespace keys = manifest_keys;
namespace errors = manifest_errors;
using csp_validator::ContentSecurityPolicyIsLegal;
using csp_validator::ContentSecurityPolicyIsSecure;
using csp_validator::SanitizeContentSecurityPolicy;
namespace {
const char kDefaultContentSecurityPolicy[] =
"script-src 'self' chrome-extension-resource:; object-src 'self'";
"script-src 'self' chrome-extension-resource:; object-src 'self';";
#define PLATFORM_APP_LOCAL_CSP_SOURCES \
"'self' data: chrome-extension-resource:"
......@@ -31,18 +32,18 @@ const char kDefaultPlatformAppContentSecurityPolicy[] =
// Platform apps can only use local resources by default.
"default-src 'self' chrome-extension-resource:;"
// For remote resources, they can fetch them via XMLHttpRequest.
"connect-src *;"
" connect-src *;"
// And serve them via data: or same-origin (blob:, filesystem:) URLs
"style-src " PLATFORM_APP_LOCAL_CSP_SOURCES " 'unsafe-inline';"
"img-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
"frame-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
"font-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
" style-src " PLATFORM_APP_LOCAL_CSP_SOURCES " 'unsafe-inline';"
" img-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
" frame-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
" font-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
// Media can be loaded from remote resources since:
// 1. <video> and <audio> have good fallback behavior when offline or under
// spotty connectivity.
// 2. Fetching via XHR and serving via blob: URLs currently does not allow
// streaming or partial buffering.
"media-src *;";
" media-src *;";
int GetValidatorOptions(Extension* extension) {
int options = csp_validator::OPTIONS_NONE;
......@@ -108,8 +109,10 @@ bool CSPHandler::Parse(Extension* extension, base::string16* error) {
kDefaultPlatformAppContentSecurityPolicy :
kDefaultContentSecurityPolicy;
CHECK(ContentSecurityPolicyIsSecure(content_security_policy,
GetValidatorOptions(extension)));
CHECK_EQ(content_security_policy,
SanitizeContentSecurityPolicy(content_security_policy,
GetValidatorOptions(extension),
NULL));
extension->SetManifestData(keys::kContentSecurityPolicy,
new CSPInfo(content_security_policy));
}
......@@ -125,11 +128,14 @@ bool CSPHandler::Parse(Extension* extension, base::string16* error) {
*error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
return false;
}
if (extension->manifest_version() >= 2 &&
!ContentSecurityPolicyIsSecure(content_security_policy,
GetValidatorOptions(extension))) {
*error = base::ASCIIToUTF16(errors::kInsecureContentSecurityPolicy);
return false;
std::string sanitized_csp;
if (extension->manifest_version() >= 2) {
std::vector<InstallWarning> warnings;
content_security_policy =
SanitizeContentSecurityPolicy(content_security_policy,
GetValidatorOptions(extension),
&warnings);
extension->AddInstallWarnings(warnings);
}
extension->SetManifestData(keys::kContentSecurityPolicy,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment