Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: extensions/common/csp_validator.cc

Issue 760513003: Only allow insecure object-src directives for whitelisted mime types (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@extensions-csp3
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « extensions/common/csp_validator.h ('k') | extensions/common/csp_validator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/common/csp_validator.h" 5 #include "extensions/common/csp_validator.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/strings/string_split.h" 9 #include "base/strings/string_split.h"
10 #include "base/strings/string_tokenizer.h" 10 #include "base/strings/string_tokenizer.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "content/public/common/url_constants.h" 12 #include "content/public/common/url_constants.h"
13 #include "extensions/common/constants.h" 13 #include "extensions/common/constants.h"
14 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 14 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
15 15
16 namespace extensions { 16 namespace extensions {
17 17
18 namespace csp_validator { 18 namespace csp_validator {
19 19
20 namespace { 20 namespace {
21 21
22 const char kDefaultSrc[] = "default-src"; 22 const char kDefaultSrc[] = "default-src";
23 const char kScriptSrc[] = "script-src"; 23 const char kScriptSrc[] = "script-src";
24 const char kObjectSrc[] = "object-src"; 24 const char kObjectSrc[] = "object-src";
25 const char kPluginTypes[] = "plugin-types";
25 26
26 const char kSandboxDirectiveName[] = "sandbox"; 27 const char kSandboxDirectiveName[] = "sandbox";
27 const char kAllowSameOriginToken[] = "allow-same-origin"; 28 const char kAllowSameOriginToken[] = "allow-same-origin";
28 const char kAllowTopNavigation[] = "allow-top-navigation"; 29 const char kAllowTopNavigation[] = "allow-top-navigation";
29 30
31 // This is the list of plugin types which are fully sandboxed and are safe to
32 // load up in an extension, regardless of the URL they are navigated to.
33 const char* const kSandboxedPluginTypes[] = {
34 "application/pdf",
35 "application/x-pnacl"
36 };
37
30 struct DirectiveStatus { 38 struct DirectiveStatus {
31 explicit DirectiveStatus(const char* name) 39 explicit DirectiveStatus(const char* name)
32 : directive_name(name) 40 : directive_name(name)
33 , seen_in_policy(false) 41 , seen_in_policy(false)
34 , is_secure(false) { 42 , is_secure(false) {
35 } 43 }
36 44
37 const char* directive_name; 45 const char* directive_name;
38 bool seen_in_policy; 46 bool seen_in_policy;
39 bool is_secure; 47 bool is_secure;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 int options) { 157 int options) {
150 if (status->seen_in_policy) 158 if (status->seen_in_policy)
151 return false; 159 return false;
152 if (directive_name != status->directive_name) 160 if (directive_name != status->directive_name)
153 return false; 161 return false;
154 status->seen_in_policy = true; 162 status->seen_in_policy = true;
155 status->is_secure = HasOnlySecureTokens(tokenizer, options); 163 status->is_secure = HasOnlySecureTokens(tokenizer, options);
156 return true; 164 return true;
157 } 165 }
158 166
167 // Parses the plugin-types directive and returns the list of mime types
168 // specified in |plugin_types|.
169 bool ParsePluginTypes(const std::string& directive_name,
170 base::StringTokenizer& tokenizer,
171 std::vector<std::string>* plugin_types) {
172 DCHECK(plugin_types);
173
174 if (directive_name != kPluginTypes || !plugin_types->empty())
175 return false;
176
177 while (tokenizer.GetNext()) {
178 std::string mime_type = tokenizer.token();
179 base::StringToLowerASCII(&mime_type);
180 // Since we're comparing the mime types to a whitelist, we don't check them
181 // for strict validity right now.
182 plugin_types->push_back(mime_type);
183 }
184
185 return true;
186 }
187
188 // Returns true if the |plugin_type| is one of the fully sandboxed plugin types.
189 bool PluginTypeAllowed(const std::string& plugin_type) {
190 for (size_t i = 0; i < arraysize(kSandboxedPluginTypes); ++i) {
191 if (plugin_type == kSandboxedPluginTypes[i])
192 return true;
193 }
194 return false;
195 }
196
197 // Returns true if the policy is allowed to contain an insecure object-src
198 // directive. This requires OPTIONS_ALLOW_INSECURE_OBJECT_SRC to be specified
199 // as an option and the plugin-types that can be loaded must be restricted to
200 // the set specified in kSandboxedPluginTypes.
201 bool AllowedToHaveInsecureObjectSrc(
202 int options,
203 const std::vector<std::string>& plugin_types) {
204 if (!(options & OPTIONS_ALLOW_INSECURE_OBJECT_SRC))
205 return false;
206
207 // plugin-types must be specified.
208 if (plugin_types.empty())
209 return false;
210
211 for (size_t i = 0; i < plugin_types.size(); ++i) {
not at google - send to devlin 2014/11/25 17:08:46 Perhaps use newfangled for-loop syntax, if you lik
raymes 2014/11/25 22:31:16 Done.
212 if (!PluginTypeAllowed(plugin_types[i]))
213 return false;
214 }
215
216 return true;
217 }
218
159 } // namespace 219 } // namespace
160 220
161 bool ContentSecurityPolicyIsLegal(const std::string& policy) { 221 bool ContentSecurityPolicyIsLegal(const std::string& policy) {
162 // We block these characters to prevent HTTP header injection when 222 // We block these characters to prevent HTTP header injection when
163 // representing the content security policy as an HTTP header. 223 // representing the content security policy as an HTTP header.
164 const char kBadChars[] = {',', '\r', '\n', '\0'}; 224 const char kBadChars[] = {',', '\r', '\n', '\0'};
165 225
166 return policy.find_first_of(kBadChars, 0, arraysize(kBadChars)) == 226 return policy.find_first_of(kBadChars, 0, arraysize(kBadChars)) ==
167 std::string::npos; 227 std::string::npos;
168 } 228 }
169 229
170 bool ContentSecurityPolicyIsSecure(const std::string& policy, 230 bool ContentSecurityPolicyIsSecure(const std::string& policy,
171 int options) { 231 int options) {
172 // See http://www.w3.org/TR/CSP/#parse-a-csp-policy for parsing algorithm. 232 // See http://www.w3.org/TR/CSP/#parse-a-csp-policy for parsing algorithm.
173 std::vector<std::string> directives; 233 std::vector<std::string> directives;
174 base::SplitString(policy, ';', &directives); 234 base::SplitString(policy, ';', &directives);
175 235
176 DirectiveStatus default_src_status(kDefaultSrc); 236 DirectiveStatus default_src_status(kDefaultSrc);
177 DirectiveStatus script_src_status(kScriptSrc); 237 DirectiveStatus script_src_status(kScriptSrc);
178 DirectiveStatus object_src_status(kObjectSrc); 238 DirectiveStatus object_src_status(kObjectSrc);
179 239
240 std::vector<std::string> plugin_types;
241
180 for (size_t i = 0; i < directives.size(); ++i) { 242 for (size_t i = 0; i < directives.size(); ++i) {
181 std::string& input = directives[i]; 243 std::string& input = directives[i];
182 base::StringTokenizer tokenizer(input, " \t\r\n"); 244 base::StringTokenizer tokenizer(input, " \t\r\n");
183 if (!tokenizer.GetNext()) 245 if (!tokenizer.GetNext())
184 continue; 246 continue;
185 247
186 std::string directive_name = tokenizer.token(); 248 std::string directive_name = tokenizer.token();
187 base::StringToLowerASCII(&directive_name); 249 base::StringToLowerASCII(&directive_name);
188 250
189 if (UpdateStatus(directive_name, tokenizer, &default_src_status, options)) 251 if (UpdateStatus(directive_name, tokenizer, &default_src_status, options))
190 continue; 252 continue;
191 if (UpdateStatus(directive_name, tokenizer, &script_src_status, options)) 253 if (UpdateStatus(directive_name, tokenizer, &script_src_status, options))
192 continue; 254 continue;
193 if (UpdateStatus(directive_name, tokenizer, &object_src_status, options)) 255 if (UpdateStatus(directive_name, tokenizer, &object_src_status, options))
194 continue; 256 continue;
257 if (ParsePluginTypes(directive_name, tokenizer, &plugin_types))
258 continue;
195 } 259 }
196 260
197 if (script_src_status.seen_in_policy && !script_src_status.is_secure) 261 if (script_src_status.seen_in_policy && !script_src_status.is_secure)
198 return false; 262 return false;
199 263
200 if (object_src_status.seen_in_policy && !object_src_status.is_secure) { 264 if (object_src_status.seen_in_policy && !object_src_status.is_secure) {
201 // Note that this does not fully check the object-src source list for 265 // Note that this does not fully check the object-src source list for
202 // validity but Blink will do this anyway. 266 // validity but Blink will do this anyway.
203 if (!(options & OPTIONS_ALLOW_INSECURE_OBJECT_SRC)) 267 if (!AllowedToHaveInsecureObjectSrc(options, plugin_types))
204 return false; 268 return false;
205 } 269 }
206 270
207 if (default_src_status.seen_in_policy && !default_src_status.is_secure) { 271 if (default_src_status.seen_in_policy && !default_src_status.is_secure) {
208 return script_src_status.seen_in_policy && 272 return script_src_status.seen_in_policy &&
209 object_src_status.seen_in_policy; 273 object_src_status.seen_in_policy;
210 } 274 }
211 275
212 return default_src_status.seen_in_policy || 276 return default_src_status.seen_in_policy ||
213 (script_src_status.seen_in_policy && object_src_status.seen_in_policy); 277 (script_src_status.seen_in_policy && object_src_status.seen_in_policy);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 } 314 }
251 } 315 }
252 } 316 }
253 317
254 return seen_sandbox; 318 return seen_sandbox;
255 } 319 }
256 320
257 } // namespace csp_validator 321 } // namespace csp_validator
258 322
259 } // namespace extensions 323 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/common/csp_validator.h ('k') | extensions/common/csp_validator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698