1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_COMMON_CSP_VALIDATOR_H_
#define EXTENSIONS_COMMON_CSP_VALIDATOR_H_
#include <string>
#include <string_view>
#include <vector>
#include "extensions/common/manifest.h"
namespace extensions {
namespace csp_validator {
// Checks whether the given `policy` is legal for use in the extension system.
// This check just ensures that the policy doesn't contain any characters that
// will cause problems when we transmit the policy in an HTTP header.
bool ContentSecurityPolicyIsLegal(const std::string& policy);
// This specifies options for configuring which CSP directives are permitted in
// extensions.
enum Options {
OPTIONS_NONE = 0,
// Allows 'unsafe-eval' to be specified as a source in a directive.
OPTIONS_ALLOW_UNSAFE_EVAL = 1 << 0,
// Allow an object-src to be specified with any sources (i.e. it may contain
// wildcards or http sources).
OPTIONS_ALLOW_INSECURE_OBJECT_SRC = 1 << 1,
};
// Helper to parse a serialized content security policy string.
// Exposed for testing.
class CSPParser {
public:
// Represents a CSP directive.
// E.g. for the directive "script-src 'self' www.google.com"
// `directive_string` is "script-src 'self' www.google.com".
// `directive_name` is "script_src".
// `directive_values` is ["'self'", "www.google.com"].
struct Directive {
Directive(std::string_view directive_string,
std::string directive_name,
std::vector<std::string_view> directive_values);
Directive(const Directive&) = delete;
Directive& operator=(const Directive&) = delete;
~Directive();
Directive(Directive&&);
Directive& operator=(Directive&&);
std::string_view directive_string;
// Must be lower case.
std::string directive_name;
std::vector<std::string_view> directive_values;
};
using DirectiveList = std::vector<Directive>;
CSPParser(std::string policy);
CSPParser(const CSPParser&) = delete;
CSPParser& operator=(const CSPParser&) = delete;
~CSPParser();
// It's not safe to move CSPParser since `directives_` refers to memory owned
// by `policy_`. Once move constructed, `directives_` will end up being in an
// invalid state, as it will point to memory owned by a "moved" string
// instance.
CSPParser(CSPParser&&) = delete;
CSPParser& operator=(CSPParser&&) = delete;
// This can contain duplicate directives (directives having the same directive
// name).
const DirectiveList& directives() const { return directives_; }
private:
void Parse();
const std::string policy_;
// This refers to memory owned by `policy_`.
DirectiveList directives_;
};
// Checks whether the given `policy` meets the minimum security requirements
// for use in the extension system.
//
// Ideally, we would like to say that an XSS vulnerability in the extension
// should not be able to execute script, even in the precense of an active
// network attacker.
//
// However, we found that it broke too many deployed extensions to limit
// 'unsafe-eval' in the script-src directive, so that is allowed as a special
// case for extensions. Platform apps disallow it.
//
// `options` is a bitmask of Options.
//
// If `warnings` is not NULL, any validation errors are appended to `warnings`.
// Returns the sanitized policy.
std::string SanitizeContentSecurityPolicy(
const std::string& policy,
std::string manifest_key,
int options,
std::vector<InstallWarning>* warnings);
// Given a `policy`, returns a sandboxed page CSP that disallows remote sources.
// The returned policy restricts the page from loading external web content
// (frames and scripts) within the page. This is done through adding 'self'
// directive source to relevant CSP directive names.
//
// If `warnings` is not nullptr, any validation errors are appended to
// `warnings`.
std::string GetSandboxedPageCSPDisallowingRemoteSources(
const std::string& policy,
std::string manifest_key,
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/
// the-iframe-element.html#attr-iframe-sandbox. The policy must have the
// "sandbox" directive, and the sandbox tokens must not include
// "allow-same-origin". Additional restrictions may be imposed depending on
// `type`.
bool ContentSecurityPolicyIsSandboxed(
const std::string& policy, Manifest::Type type);
// Returns whether the given `content_security_policy` prevents remote scripts.
// If not, populates `error`.
bool DoesCSPDisallowRemoteCode(const std::string& content_security_policy,
std::string_view manifest_key,
std::u16string* error);
} // namespace csp_validator
} // namespace extensions
#endif // EXTENSIONS_COMMON_CSP_VALIDATOR_H_
|