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
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
  346
  347
  348
  349
  350
  351
  352
  353
  354
  355
  356
  357
  358
  359
  360
  361
  362
  363
  364
  365
  366
  367
  368
  369
  370
  371
  372
  373
  374
  375
  376
  377
  378
  379
  380
  381
  382
  383
  384
  385
  386

content / public / browser / child_process_security_policy.h [blame]

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_PUBLIC_BROWSER_CHILD_PROCESS_SECURITY_POLICY_H_
#define CONTENT_PUBLIC_BROWSER_CHILD_PROCESS_SECURITY_POLICY_H_

#include <optional>
#include <string>
#include <string_view>
#include <vector>

#include "content/common/content_export.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace base {
class FilePath;
}

namespace content {

class BrowserContext;

// The ChildProcessSecurityPolicy class is used to grant and revoke security
// capabilities for child processes.  For example, it restricts whether a child
// process is permitted to load file:// URLs based on whether the process
// has ever been commanded to load file:// URLs by the browser.
//
// ChildProcessSecurityPolicy is a singleton that may be used on any thread.
//
class ChildProcessSecurityPolicy {
 public:
  virtual ~ChildProcessSecurityPolicy() {}

  // There is one global ChildProcessSecurityPolicy object for the entire
  // browser process.  The object returned by this method may be accessed on
  // any thread.
  static CONTENT_EXPORT ChildProcessSecurityPolicy* GetInstance();

  // Web-safe schemes can be requested by any child process.  Once a web-safe
  // scheme has been registered, any child process can request URLs whose
  // origins use that scheme. There is no mechanism for revoking web-safe
  // schemes.
  //
  // Only call this function if URLs of this scheme are okay to host in
  // any ordinary renderer process.
  //
  // Registering 'your-scheme' as web-safe also causes 'blob:your-scheme://'
  // and 'filesystem:your-scheme://' URLs to be considered web-safe.
  virtual void RegisterWebSafeScheme(const std::string& scheme) = 0;

  // More restrictive variant of RegisterWebSafeScheme; URLs with this scheme
  // may be requested by any child process, but navigations to this scheme may
  // only commit in child processes that have been explicitly granted
  // permission to do so.
  //
  // |always_allow_in_origin_headers| controls whether this scheme is allowed to
  // appear as the Origin HTTP header in outbound requests, even if the
  // originating process does not have permission to commit this scheme. This
  // may be necessary if the scheme is used in conjunction with blink's
  // IsolatedWorldSecurityOrigin mechanism, as for extension content scripts.
  virtual void RegisterWebSafeIsolatedScheme(
      const std::string& scheme,
      bool always_allow_in_origin_headers) = 0;

  // Returns true iff |scheme| has been registered as a web-safe scheme.
  // TODO(nick): https://crbug.com/651534 This function does not have enough
  // information to render an appropriate judgment for blob and filesystem URLs;
  // change it to accept an URL instead.
  virtual bool IsWebSafeScheme(const std::string& scheme) = 0;

  // This permission grants only read access to a file.
  // Whenever the user picks a file from a <input type="file"> element, the
  // browser should call this function to grant the child process the capability
  // to upload the file to the web. Grants FILE_PERMISSION_READ_ONLY.
  virtual void GrantReadFile(int child_id, const base::FilePath& file) = 0;

  // This permission grants creation, read, and full write access to a file,
  // including attributes.
  virtual void GrantCreateReadWriteFile(int child_id,
                                        const base::FilePath& file) = 0;

  // This permission grants copy-into permission for |dir|.
  virtual void GrantCopyInto(int child_id, const base::FilePath& dir) = 0;

  // This permission grants delete permission for |dir|.
  virtual void GrantDeleteFrom(int child_id, const base::FilePath& dir) = 0;

  // Determine whether the process has the capability to request the URL.
  // Before servicing a child process's request for a URL, the content layer
  // calls this method to determine whether it is safe. CanRequestURL() allows
  // for requests that might lead to cross-process navigations or external
  // protocol handlers.
  //
  // Note that this check is different from checking whether a document with
  // the given URL can be committed in a process; that latter check is more
  // restrictive and is performed within //content (see
  // ChildProcessSecurityPolicyImpl::CanCommitURL).
  virtual bool CanRequestURL(int child_id, const GURL& url) = 0;

  // These methods verify whether or not the child process has been granted
  // permissions perform these functions on |file|.

  // Before servicing a child process's request to upload a file to the web, the
  // browser should call this method to determine whether the process has the
  // capability to upload the requested file.
  virtual bool CanReadFile(int child_id, const base::FilePath& file) = 0;
  virtual bool CanCreateReadWriteFile(int child_id,
                                      const base::FilePath& file) = 0;

  // Grants read access permission to the given isolated file system
  // identified by |filesystem_id|. An isolated file system can be
  // created for a set of native files/directories (like dropped files)
  // using storage::IsolatedContext. A child process needs to be granted
  // permission to the file system to access the files in it using
  // file system URL. You do NOT need to give direct permission to
  // individual file paths.
  //
  // Note: files/directories in the same file system share the same
  // permission as far as they are accessed via the file system, i.e.
  // using the file system URL (tip: you can create a new file system
  // to give different permission to part of files).
  virtual void GrantReadFileSystem(int child_id,
                                   const std::string& filesystem_id) = 0;

  // Grants write access permission to the given isolated file system
  // identified by |filesystem_id|.  See comments for GrantReadFileSystem
  // for more details.  You do NOT need to give direct permission to
  // individual file paths.
  //
  // This must be called with a great care as this gives write permission
  // to all files/directories included in the file system.
  virtual void GrantWriteFileSystem(int child_id,
                                    const std::string& filesystem_id) = 0;

  // Grants create file permission to the given isolated file system
  // identified by |filesystem_id|.  See comments for GrantReadFileSystem
  // for more details.  You do NOT need to give direct permission to
  // individual file paths.
  //
  // This must be called with a great care as this gives create permission
  // within all directories included in the file system.
  virtual void GrantCreateFileForFileSystem(
      int child_id,
      const std::string& filesystem_id) = 0;

  // Grants create, read and write access permissions to the given isolated
  // file system identified by |filesystem_id|.  See comments for
  // GrantReadFileSystem for more details.  You do NOT need to give direct
  // permission to individual file paths.
  //
  // This must be called with a great care as this gives create, read and write
  // permissions to all files/directories included in the file system.
  virtual void GrantCreateReadWriteFileSystem(
      int child_id,
      const std::string& filesystem_id) = 0;

  // Grants permission to copy-into filesystem |filesystem_id|. 'copy-into'
  // is used to allow copying files into the destination filesystem without
  // granting more general create and write permissions.
  virtual void GrantCopyIntoFileSystem(int child_id,
                                       const std::string& filesystem_id) = 0;

  // Grants permission to delete from filesystem |filesystem_id|. 'delete-from'
  // is used to allow deleting files into the destination filesystem without
  // granting more general create and write permissions.
  virtual void GrantDeleteFromFileSystem(int child_id,
                                         const std::string& filesystem_id) = 0;

  // Grants the child process the capability to commit URLs with the provided
  // origin. Usage should be extremely rare: the content framework already
  // automatically grants this privilege as needed on successful navigation to a
  // URL.
  // If you think you need this, please reach out to site-isolation-dev@ first.
  virtual void GrantCommitOrigin(int child_id, const url::Origin& origin) = 0;
  //
  // Grants the child process the capability to request URLs with the provided
  // origin.
  virtual void GrantRequestOrigin(int child_id, const url::Origin& origin) = 0;

  // Grants the child process the capability to request URLs of the provided
  // scheme.
  virtual void GrantRequestScheme(int child_id, const std::string& scheme) = 0;

  // Returns true if read access has been granted to |filesystem_id|.
  virtual bool CanReadFileSystem(int child_id,
                                 const std::string& filesystem_id) = 0;

  // Returns true if read and write access has been granted to |filesystem_id|.
  virtual bool CanReadWriteFileSystem(int child_id,
                                      const std::string& filesystem_id) = 0;

  // Returns true if copy-into access has been granted to |filesystem_id|.
  virtual bool CanCopyIntoFileSystem(int child_id,
                                     const std::string& filesystem_id) = 0;

  // Returns true if delete-from access has been granted to |filesystem_id|.
  virtual bool CanDeleteFromFileSystem(int child_id,
                                       const std::string& filesystem_id) = 0;

  // Returns true if the specified child_id has been granted WebUI bindings.
  // The browser should check this property before assuming the child process
  // is allowed to use WebUI bindings.
  virtual bool HasWebUIBindings(int child_id) = 0;

  // Grants permission to send messages to any MIDI devices.
  virtual void GrantSendMidiMessage(int child_id) = 0;

  // Grants permission to send system exclusive (SysEx) messages to any MIDI
  // devices.
  virtual void GrantSendMidiSysExMessage(int child_id) = 0;

  // This function checks whether a process is allowed to read and/or modify
  // `origin`'s data such as passwords, cookies, or localStorage. Generally,
  // this implies that an instance of `origin` must have previously been
  // committed in this process (e.g., via a navigation or worker instantiation).
  //
  // Internally, this function performs two kinds of security checks:
  // - "Jail" check: ensures that a process locked to a particular site can only
  //   access data belonging to that site.
  // - "Citadel" check: ensures that a process that is *not* locked to a
  //   particular site does not access data belonging to a site that requires a
  //   dedicated process. This check is mainly relevant on Android, where only
  //   some sites require site isolation.
  //
  // This is one of two core ways of enforcing Site Isolation (see
  // docs/process_model_and_site_isolation.md), the other being `HostsOrigin()`
  // below. Compared to `HostsOrigin()`, this check is more strict.  In
  // particular, it may block access for renderer processes that should never
  // need to access any origin's data, such as processes containing only
  // documents with opaque origins (e.g., from sandboxed frames), or processes
  // containing more restricted content types like PDF.
  virtual bool CanAccessDataForOrigin(int child_id,
                                      const url::Origin& origin) = 0;

  // This function checks whether a process has an instance of a particular
  // `origin`, either because it has committed a document or has instantiated a
  // worker with that origin. This can be used to validate initiator or source
  // origins that are included in messages or IPCs received from the renderer,
  // such as the source origin for postMessage. Generally, this function
  // performs similar enforcements to `CanAccessDataForOrigin()` above,
  // including both jail and citadel checks. In contrast to
  // `CanAccessDataForOrigin()`, this function permits access from opaque
  // origins, making it more suitable to use for APIs that are allowed in such
  // origins (such as postMessage).
  //
  // Subtle note: due to shutdown races, where a document/worker destruction may
  // race with processing legitimate IPCs on behalf of `origin` from the
  // renderer, this function actually checks for the process either *currently*
  // having an origin, or having hosted it in the *past* (but not necessarily
  // now).
  virtual bool HostsOrigin(int child_id, const url::Origin& origin) = 0;

  // Defines available sources of isolated origins.  This should be specified
  // when adding isolated origins with the AddFutureIsolatedOrigins() call
  // below.
  enum class IsolatedOriginSource {
    // Used for origins that are hardcoded into the browser.
    BUILT_IN,
    // Used for origins that are specified from the command line, i.e.
    // --isolate-origins.
    COMMAND_LINE,
    // Used for origins that are configured through field trials.
    FIELD_TRIAL,
    // Used for origins defined by an administrator (e.g., via enterprise
    // policy).
    POLICY,
    // Used for origins that are isolated based on user-triggered runtime
    // heuristics.
    USER_TRIGGERED,
    // Used for origins that are isolated based on runtime heuristics triggered
    // directly by web pages, such as headers.
    WEB_TRIGGERED,
    // Used for testing purposes.
    TEST
  };

  // Add |origins| to the list of origins that require process isolation.  When
  // making process model decisions for such origins, the scheme+host tuple
  // rather than scheme and eTLD+1 will be used.  SiteInstances for these
  // origins will also use the full host of the isolated origin as site URL.
  //
  // Subdomains of an isolated origin are considered to be part of that
  // origin's site.  For example, if https://isolated.foo.com is added as an
  // isolated origin, then https://bar.isolated.foo.com will be considered part
  // of the site for https://isolated.foo.com.
  //
  // Note that origins from |origins| must not be unique - URLs that render with
  // unique origins, such as data: URLs, are not supported. Non-standard
  // schemes are also not supported.  Sandboxed frames (e.g., <iframe sandbox>)
  // *are* supported, since process placement decisions will be based on the
  // URLs such frames navigate to, and not the origin of committed documents
  // (which might be unique).  If an isolated origin opens an about:blank
  // popup, it will stay in the isolated origin's process. Nested URLs
  // (filesystem: and blob:) retain process isolation behavior of their inner
  // origin.
  //
  // Note that it is okay if |origins| contains duplicates - the set of origins
  // will be deduplicated inside the method.
  //
  // The new isolated origins will apply only to BrowsingInstances and renderer
  // processes created *after* this call.  This is necessary to not break
  // scripting relationships between same-origin iframes in existing
  // BrowsingInstances.  To do this, this function internally determines a
  // threshold BrowsingInstance ID that is higher than all existing
  // BrowsingInstance IDs but lower than future BrowsingInstance IDs, and
  // associates it with each of the |origins|. If an origin had already been
  // isolated prior to calling this, it is ignored, and its threshold is not
  // updated.
  //
  // |source| describes the context/reason for adding the new isolated origins;
  // see comments on IsolatedOriginSource.
  //
  // If |browser_context| is non-null, the new isolated origins added via this
  // function will apply only within that BrowserContext.  If |browser_context|
  // is null, the new isolated origins will apply globally in *all*
  // BrowserContexts (but still subject to the BrowsingInstance ID cutoff in
  // the previous paragraph).
  //
  // This function may be called again for the same origin but different
  // |browser_context|. In that case, the origin will be isolated in all
  // BrowserContexts for which this function has been called.  However,
  // attempts to re-add an origin for the same |browser_context| will be
  // ignored.
  virtual void AddFutureIsolatedOrigins(
      const std::vector<url::Origin>& origins,
      IsolatedOriginSource source,
      BrowserContext* browser_context = nullptr) = 0;

  // Semantically identical to the above, but accepts a string of comma
  // separated origins. |origins_to_add| can contain both wildcard and
  // non-wildcard origins, e.g. "https://[*.]foo.com,https://bar.com".
  //
  // Wildcard origins provide a way to treat all subdomains under the specified
  // host and scheme as distinct isolated origins. For example,
  // https://[*.]foo.com would isolate https://foo.com, https://bar.foo.com and
  // https://qux.baz.foo.com all in separate processes. Adding a wildcard origin
  // implies breaking document.domain for all of its subdomains.
  //
  // Note that wildcards can only be added using this version of
  // AddFutureIsolatedOrigins(); they cannot be specified in a url::Origin().
  virtual void AddFutureIsolatedOrigins(
      std::string_view origins_to_add,
      IsolatedOriginSource source,
      BrowserContext* browser_context = nullptr) = 0;

  // Returns true if |origin| is a globally (not per-profile) isolated origin.
  virtual bool IsGloballyIsolatedOriginForTesting(
      const url::Origin& origin) = 0;

  // Returns the set of currently active isolated origins, optionally filtered
  // by the source of how they were added and/or by BrowserContext.
  //
  // If |source| is provided, only origins that were added with the same source
  // will be returned; if |source| is std::nullopt, origins from all sources
  // will be returned.
  //
  // If |browser_context| is null, only globally applicable origins will be
  // returned.  If |browser_context| is non-null, only origins that apply
  // within that particular BrowserContext will be returned (note that this
  // includes both matching per-profile isolated origins as well as globally
  // applicable origins which apply to |browser_context| by definition).
  //
  // Origins returned by this function only include origins that would apply to
  // any future BrowsingInstance (browsing context group).  Origins that were
  // isolated only in specific BrowsingInstances are not included.  (In
  // particular, this excludes BrowsingInstance-specific isolated origins for
  // Origin-Agent-Cluster as well as COOP documents loaded without user
  // activation.)
  virtual std::vector<url::Origin> GetIsolatedOrigins(
      std::optional<IsolatedOriginSource> source = std::nullopt,
      BrowserContext* browser_context = nullptr) = 0;

  // Returns whether the site of |origin| is isolated and was added by the
  // |source| to be isolated.
  virtual bool IsIsolatedSiteFromSource(const url::Origin& origin,
                                        IsolatedOriginSource source) = 0;

  // Clears all isolated origins.  This is unsafe to use outside of testing.
  virtual void ClearIsolatedOriginsForTesting() = 0;
};

}  // namespace content

#endif  // CONTENT_PUBLIC_BROWSER_CHILD_PROCESS_SECURITY_POLICY_H_