summaryrefslogtreecommitdiffstats
path: root/extensions/common
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/common')
-rw-r--r--extensions/common/csp_validator.cc184
-rw-r--r--extensions/common/csp_validator.h9
-rw-r--r--extensions/common/csp_validator_unittest.cc525
-rw-r--r--extensions/common/manifest_constants.cc17
-rw-r--r--extensions/common/manifest_constants.h2
-rw-r--r--extensions/common/manifest_handlers/csp_info.cc36
6 files changed, 496 insertions, 277 deletions
diff --git a/extensions/common/csp_validator.cc b/extensions/common/csp_validator.cc
index 6895b31..371d7f8 100644
--- a/extensions/common/csp_validator.cc
+++ b/extensions/common/csp_validator.cc
@@ -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))
- return false;
+ 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;
}
-
- 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))
- continue;
- if (UpdateStatus(directive_name, tokenizer, &script_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, &object_src_status, options))
+ if (UpdateStatus(directive_name, &tokenizer, &script_src_status, options,
+ &sane_csp_parts, warnings))
continue;
- if (ParsePluginTypes(directive_name, tokenizer, &plugin_types))
+ if (!allow_insecure_object_src &&
+ UpdateStatus(directive_name, &tokenizer, &object_src_status, options,
+ &sane_csp_parts, warnings))
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(
diff --git a/extensions/common/csp_validator.h b/extensions/common/csp_validator.h
index e8aa78c..93676b0 100644
--- a/extensions/common/csp_validator.h
+++ b/extensions/common/csp_validator.h
@@ -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/
diff --git a/extensions/common/csp_validator_unittest.cc b/extensions/common/csp_validator_unittest.cc
index 1afa0b1..a9728f9 100644
--- a/extensions/common/csp_validator_unittest.cc
+++ b/extensions/common/csp_validator_unittest.cc
@@ -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_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(
+ 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 *; script-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL));
- EXPECT_FALSE(ContentSecurityPolicyIsSecure(
+ 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_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",
- OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
- EXPECT_FALSE(ContentSecurityPolicyIsSecure(
- "script-src 'self'; object-src *; "
- "plugin-types application/x-shockwave-flash",
- OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
- EXPECT_FALSE(ContentSecurityPolicyIsSecure(
- "script-src 'self'; object-src *; "
- "plugin-types application/x-shockwave-flash application/pdf",
- OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
- EXPECT_TRUE(ContentSecurityPolicyIsSecure(
- "script-src 'self'; object-src http://www.example.com; "
- "plugin-types application/pdf",
- OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
- EXPECT_TRUE(ContentSecurityPolicyIsSecure(
- "object-src http://www.example.com blob:; script-src 'self'; "
- "plugin-types application/pdf",
- OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
- EXPECT_TRUE(ContentSecurityPolicyIsSecure(
- "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",
- OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
+
+ 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_TRUE(CheckSanitizeCSP(
+ "script-src 'self'; object-src *; "
+ "plugin-types application/x-shockwave-flash",
+ 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,
+ "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;",
+ OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
+ EXPECT_TRUE(CheckSanitizeCSP(
+ "object-src http://www.example.com blob:; script-src 'self'; "
+ "plugin-types application/pdf;",
+ OPTIONS_ALLOW_INSECURE_OBJECT_SRC));
+ EXPECT_TRUE(CheckSanitizeCSP(
+ "script-src 'self'; object-src http://*.example.com; "
+ "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) {
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc
index 40b7d4e..4565184 100644
--- a/extensions/common/manifest_constants.cc
+++ b/extensions/common/manifest_constants.cc
@@ -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[] =
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h
index d395033..7ab779c 100644
--- a/extensions/common/manifest_constants.h
+++ b/extensions/common/manifest_constants.h
@@ -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[];
diff --git a/extensions/common/manifest_handlers/csp_info.cc b/extensions/common/manifest_handlers/csp_info.cc
index 2c3838f..e756995 100644
--- a/extensions/common/manifest_handlers/csp_info.cc
+++ b/extensions/common/manifest_handlers/csp_info.cc
@@ -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,