Index: extensions/common/csp_validator.cc |
diff --git a/extensions/common/csp_validator.cc b/extensions/common/csp_validator.cc |
index 3224ad6e1324d3348bb6d30be6372e2d982aa8a9..6895b31fdb0e7b8f8cd219f8709db6f2dd4b2a7e 100644 |
--- a/extensions/common/csp_validator.cc |
+++ b/extensions/common/csp_validator.cc |
@@ -22,11 +22,20 @@ namespace { |
const char kDefaultSrc[] = "default-src"; |
const char kScriptSrc[] = "script-src"; |
const char kObjectSrc[] = "object-src"; |
+const char kPluginTypes[] = "plugin-types"; |
const char kSandboxDirectiveName[] = "sandbox"; |
const char kAllowSameOriginToken[] = "allow-same-origin"; |
const char kAllowTopNavigation[] = "allow-top-navigation"; |
+// This is the list of plugin types which are fully sandboxed and are safe to |
+// load up in an extension, regardless of the URL they are navigated to. |
+const char* const kSandboxedPluginTypes[] = { |
+ "application/pdf", |
+ "application/x-google-chrome-pdf", |
+ "application/x-pnacl" |
+}; |
+ |
struct DirectiveStatus { |
explicit DirectiveStatus(const char* name) |
: directive_name(name) |
@@ -156,6 +165,58 @@ bool UpdateStatus(const std::string& directive_name, |
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); |
+ } |
+ |
+ return true; |
+} |
+ |
+// Returns true if the |plugin_type| is one of the fully sandboxed plugin types. |
+bool PluginTypeAllowed(const std::string& plugin_type) { |
+ for (size_t i = 0; i < arraysize(kSandboxedPluginTypes); ++i) { |
+ if (plugin_type == kSandboxedPluginTypes[i]) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+// Returns true if the policy is allowed to contain an insecure object-src |
+// directive. This requires OPTIONS_ALLOW_INSECURE_OBJECT_SRC to be specified |
+// as an option and the plugin-types that can be loaded must be restricted to |
+// the set specified in kSandboxedPluginTypes. |
+bool AllowedToHaveInsecureObjectSrc( |
+ int options, |
+ const std::vector<std::string>& plugin_types) { |
+ 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; |
+ } |
+ |
+ return true; |
+} |
+ |
} // namespace |
bool ContentSecurityPolicyIsLegal(const std::string& policy) { |
@@ -177,6 +238,8 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy, |
DirectiveStatus script_src_status(kScriptSrc); |
DirectiveStatus object_src_status(kObjectSrc); |
+ std::vector<std::string> plugin_types; |
+ |
for (size_t i = 0; i < directives.size(); ++i) { |
std::string& input = directives[i]; |
base::StringTokenizer tokenizer(input, " \t\r\n"); |
@@ -192,6 +255,8 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy, |
continue; |
if (UpdateStatus(directive_name, tokenizer, &object_src_status, options)) |
continue; |
+ if (ParsePluginTypes(directive_name, tokenizer, &plugin_types)) |
+ continue; |
} |
if (script_src_status.seen_in_policy && !script_src_status.is_secure) |
@@ -200,7 +265,7 @@ bool ContentSecurityPolicyIsSecure(const std::string& policy, |
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 (!(options & OPTIONS_ALLOW_INSECURE_OBJECT_SRC)) |
+ if (!AllowedToHaveInsecureObjectSrc(options, plugin_types)) |
return false; |
} |