summaryrefslogtreecommitdiff
path: root/chromium/docs/security/origin-vs-url.md
blob: c608f8b9d677ed754bdb735b91d837365aba190c (plain)
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
# Use origin (rather than URL) for security decisions.

URLs are often not sufficient for security decisions, since the origin
may not be present in the URL (e.g., `about:blank`),
may be tricky to parse (e.g., `blob:` or `filesystem:` URLs),
or may be
[opaque](https://html.spec.whatwg.org/multipage/origin.html#concept-origin-opaque)
despite a normal-looking URL (e.g., the security context may be
[sandboxed](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox)).
Use origins whenever possible.


## Use `GetLastCommittedOrigin()` or `GetSecurityContext()`.

**_Good_**
```c++
// Example of browser-side code.
content::RenderFrameHost* frame = ...;
if (safelist.Matches(frame->GetLastCommittedOrigin()) {
  // ...
}

// Example of renderer-side code.  Note that browser-side checks are still
// needed to ensure that a compromised renderer cannot bypass renderer-side-only
// checks.
blink::Frame* frame = ...;
if (safelist.Matches(frame->GetSecurityContext()->GetSecurityOrigin()) {
  // ...
}
```

**_Bad_**
```c++
// Example of browser-side code.
content::RenderFrameHost* frame = ...;
if (safelist.Matches(frame->GetLastCommittedURL()) {
  // BUG: doesn't work for about:blank or sandboxed frames.
}

// Example of renderer-side code.  Note that browser-side checks are still
// needed to ensure that a compromised renderer cannot bypass renderer-side-only
// checks.
blink::LocalFrame* frame = ...;
if (safelist.Matches(frame->GetDocument()->Url()) {
  // BUG: doesn't work for about:blank or sandboxed frames.
  // BUG: doesn't work for RemoteFrame(s) which don't have a local Document
  //      object and don't know the URL (only the origin) of the frame.
}
```


## Don't use the `GURL` type to store origins.

`GURL origin` is an anti-pattern - representing origins as a URL-focused data
type means that 1) some information is lost (e.g., origin's nonce and precursor
information) and 2) some unnecessary information may be present (e.g., URL path
and/or query parts are never part of an origin).

Use the following datatypes to represent origins:

- C++: `url::Origin` or `blink::SecurityOrigin`
  (instead of `GURL` or `blink::KURL`).
- Mojo: `url.mojom.Origin`
  (instead of `url.mojom.Url`).
  Remember to
  [validate data](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/mojo.md#Validate-privilege_presuming-data-received-over-IPC)
  received over IPC from untrustworthy processes
  or even better
  [avoid sending origins](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/mojo.md#Do-not-send-unnecessary-or-privilege_presuming-data)
  in the first place.
- Java: `org.chromium.url.Origin`
  (see also `url::Origin::FromJavaObject`
  and `url::Origin::CreateJavaObject`).


## Avoid converting URLs to origins.

**_Good_**
```c++
url::Origin origin = GetLastCommittedOrigin();
```

**_Bad_**
```c++
GURL url = ...;
GURL origin = url.GetOrigin();
// BUG: |origin| will be empty if |url| is a blob: URL like
//      "blob:http://origin/guid-goes-here".
// BUG: |origin| will be incorrect if |url| is an "about:blank" URL
//      or if |url| came from a sandboxed frame.
// BUG: |origin| will be incorrect when |url| (rather than
//      |base_url_for_data_url|) is used when working with loadDataWithBaseUrl
//      (see also https://crbug.com/1201514).
// NOTE: |GURL origin| is also an anti-pattern; see the "Use correct type to
//       represent origins" section below.
```

**_Risky_**
```c++
// If you know what you are doing (e.g., don't care about "about:blank", about
// sandboxed frames, or about loadDataWithBaseUrl) and really need to convert
// a URL into an origin, then url::Origin::Create will correctly handle
// filesystem: and/or blob: URLs (unlike the "bad" example above).
GURL url = ...;
url::Origin origin = url::Origin::Create(url);
// |origin| will be "http://origin/" if |url| is a blob: or filesystem: URL
// like "blob:http://origin/guid-goes-here".
```