OLD | NEW |
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 <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <initializer_list> | 9 #include <initializer_list> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/callback.h" | 13 #include "base/callback.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/strings/string_piece.h" |
15 #include "base/strings/string_split.h" | 16 #include "base/strings/string_split.h" |
16 #include "base/strings/string_tokenizer.h" | 17 #include "base/strings/string_tokenizer.h" |
17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
19 #include "content/public/common/url_constants.h" | 20 #include "content/public/common/url_constants.h" |
20 #include "extensions/common/constants.h" | 21 #include "extensions/common/constants.h" |
21 #include "extensions/common/error_utils.h" | 22 #include "extensions/common/error_utils.h" |
22 #include "extensions/common/install_warning.h" | 23 #include "extensions/common/install_warning.h" |
23 #include "extensions/common/manifest_constants.h" | 24 #include "extensions/common/manifest_constants.h" |
24 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 25 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 | 191 |
191 InstallWarning CSPInstallWarning(const std::string& csp_warning) { | 192 InstallWarning CSPInstallWarning(const std::string& csp_warning) { |
192 return InstallWarning(csp_warning, manifest_keys::kContentSecurityPolicy); | 193 return InstallWarning(csp_warning, manifest_keys::kContentSecurityPolicy); |
193 } | 194 } |
194 | 195 |
195 std::string GetSecureDirectiveValues( | 196 std::string GetSecureDirectiveValues( |
196 int options, | 197 int options, |
197 const std::string& directive_name, | 198 const std::string& directive_name, |
198 const std::vector<base::StringPiece>& directive_values, | 199 const std::vector<base::StringPiece>& directive_values, |
199 std::vector<InstallWarning>* warnings) { | 200 std::vector<InstallWarning>* warnings) { |
200 std::vector<std::string> sane_csp_parts(1, directive_name); | 201 std::vector<base::StringPiece> sane_csp_parts{directive_name}; |
201 for (base::StringPiece source_literal : directive_values) { | 202 for (base::StringPiece source_literal : directive_values) { |
202 std::string source_lower = base::ToLowerASCII(source_literal); | 203 std::string source_lower = base::ToLowerASCII(source_literal); |
203 bool is_secure_csp_token = false; | 204 bool is_secure_csp_token = false; |
204 | 205 |
205 // We might need to relax this whitelist over time. | 206 // We might need to relax this whitelist over time. |
206 if (source_lower == "'self'" || source_lower == "'none'" || | 207 if (source_lower == "'self'" || source_lower == "'none'" || |
207 source_lower == "http://127.0.0.1" || source_lower == "blob:" || | 208 source_lower == "http://127.0.0.1" || source_lower == "blob:" || |
208 source_lower == "filesystem:" || source_lower == "http://localhost" || | 209 source_lower == "filesystem:" || source_lower == "http://localhost" || |
209 base::StartsWith(source_lower, "http://127.0.0.1:", | 210 base::StartsWith(source_lower, "http://127.0.0.1:", |
210 base::CompareCase::SENSITIVE) || | 211 base::CompareCase::SENSITIVE) || |
(...skipping 13 matching lines...) Expand all Loading... |
224 } else if (base::StartsWith(source_lower, "chrome-extension-resource:", | 225 } else if (base::StartsWith(source_lower, "chrome-extension-resource:", |
225 base::CompareCase::SENSITIVE)) { | 226 base::CompareCase::SENSITIVE)) { |
226 // The "chrome-extension-resource" scheme has been removed from the | 227 // The "chrome-extension-resource" scheme has been removed from the |
227 // codebase, but it may still appear in existing CSPs. We continue to | 228 // codebase, but it may still appear in existing CSPs. We continue to |
228 // allow it here for compatibility. Requests on this scheme will not | 229 // allow it here for compatibility. Requests on this scheme will not |
229 // return any kind of network response. | 230 // return any kind of network response. |
230 is_secure_csp_token = true; | 231 is_secure_csp_token = true; |
231 } | 232 } |
232 | 233 |
233 if (is_secure_csp_token) { | 234 if (is_secure_csp_token) { |
234 sane_csp_parts.push_back(source_literal.as_string()); | 235 sane_csp_parts.push_back(source_literal); |
235 } else if (warnings) { | 236 } else if (warnings) { |
236 warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage( | 237 warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage( |
237 manifest_errors::kInvalidCSPInsecureValue, source_literal.as_string(), | 238 manifest_errors::kInvalidCSPInsecureValue, source_literal.as_string(), |
238 directive_name))); | 239 directive_name))); |
239 } | 240 } |
240 } | 241 } |
241 // End of CSP directive that was started at the beginning of this method. If | 242 // End of CSP directive that was started at the beginning of this method. If |
242 // none of the values are secure, the policy will be empty and default to | 243 // none of the values are secure, the policy will be empty and default to |
243 // 'none', which is secure. | 244 // 'none', which is secure. |
244 sane_csp_parts.back().push_back(kDirectiveSeparator); | 245 std::string last_part = sane_csp_parts.back().as_string(); |
| 246 last_part.push_back(kDirectiveSeparator); |
| 247 sane_csp_parts.back() = last_part; |
245 return base::JoinString(sane_csp_parts, " "); | 248 return base::JoinString(sane_csp_parts, " "); |
246 } | 249 } |
247 | 250 |
248 // Given a CSP directive-token for app sandbox, returns a secure value of that | 251 // Given a CSP directive-token for app sandbox, returns a secure value of that |
249 // directive. | 252 // directive. |
250 // The directive-token's name is |directive_name| and its values are splitted | 253 // The directive-token's name is |directive_name| and its values are splitted |
251 // into |directive_values|. | 254 // into |directive_values|. |
252 std::string GetAppSandboxSecureDirectiveValues( | 255 std::string GetAppSandboxSecureDirectiveValues( |
253 const std::string& directive_name, | 256 const std::string& directive_name, |
254 const std::vector<base::StringPiece>& directive_values, | 257 const std::vector<base::StringPiece>& directive_values, |
255 std::vector<InstallWarning>* warnings) { | 258 std::vector<InstallWarning>* warnings) { |
256 std::vector<std::string> sane_csp_parts(1, directive_name); | 259 std::vector<std::string> sane_csp_parts{directive_name}; |
257 bool seen_self_or_none = false; | 260 bool seen_self_or_none = false; |
258 for (base::StringPiece source_literal : directive_values) { | 261 for (base::StringPiece source_literal : directive_values) { |
259 std::string source_lower = base::ToLowerASCII(source_literal); | 262 std::string source_lower = base::ToLowerASCII(source_literal); |
260 | 263 |
261 // Keyword directive sources are surrounded with quotes, e.g. 'self', | 264 // Keyword directive sources are surrounded with quotes, e.g. 'self', |
262 // 'sha256-...', 'unsafe-eval', 'nonce-...'. These do not specify a remote | 265 // 'sha256-...', 'unsafe-eval', 'nonce-...'. These do not specify a remote |
263 // host or '*', so keep them and restrict the rest. | 266 // host or '*', so keep them and restrict the rest. |
264 if (source_lower.size() > 1u && source_lower[0] == '\'' && | 267 if (source_lower.size() > 1u && source_lower[0] == '\'' && |
265 source_lower.back() == '\'') { | 268 source_lower.back() == '\'') { |
266 seen_self_or_none |= source_lower == "'none'" || source_lower == "'self'"; | 269 seen_self_or_none |= source_lower == "'none'" || source_lower == "'self'"; |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 } | 589 } |
587 } | 590 } |
588 } | 591 } |
589 | 592 |
590 return seen_sandbox; | 593 return seen_sandbox; |
591 } | 594 } |
592 | 595 |
593 } // namespace csp_validator | 596 } // namespace csp_validator |
594 | 597 |
595 } // namespace extensions | 598 } // namespace extensions |
OLD | NEW |