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 despite a normal-looking URL (e.g., the security context may be sandboxed). Use origins whenever possible.
GetLastCommittedOrigin()
or GetSecurityContext()
.// 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()) { // ... }
// 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. }
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:
url::Origin
or blink::SecurityOrigin
(instead of GURL
or blink::KURL
).url.mojom.Origin
(instead of url.mojom.Url
). Remember to validate data received over IPC from untrustworthy processes or even better avoid sending origins in the first place.org.chromium.url.Origin
(see also url::Origin::FromJavaObject
and url::Origin::ToJavaObject
).url::Origin origin = GetLastCommittedOrigin();
GURL url = ...; GURL origin = url.DeprecatedGetOriginAsURL(); // BUG: `origin` will be incorrect if `url` is an "about:blank" URL // BUG: `origin` will be incorrect 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). // BUG: `origin` will be empty if `url` is a blob: URL like // "blob:http://origin/guid-goes-here". // NOTE: `GURL origin` is also an anti-pattern; see the "Use correct type to // represent origins" section below. // Blink-specific example: KURL url = ...; scoped_refptr<SecurityOrigin> origin = SecurityOrigin::Create(url); // BUG: `origin` will be incorrect if `url` is an "about:blank" URL // BUG: `origin` will be incorrect if `url` came from a sandboxed frame.
If you know what you are doing and really need to convert a URL into an origin, then you can consider using url::Origin::Create
, url::SchemeHostPort
, or url::Origin::Resolve
(noting the limitations of those APIs - see below for more details).
const GURL& url = ...; // WARNING: `url::Origin::Create(url)` can give unexpected results if: // 1) `url` is "about:blank", or "about:srcdoc" // (returning unique, opaque origin rather than the real origin of the frame) // 2) `url` comes from a sandboxed frame // (potentially returning a non-opaque origin, when an opaque one is needed) // 3) `base_url_for_data_url` should be used instead of `url` // // WARNING: `url::Origin::Create(url)` has some additional subtleties: // 4) if `url` is a blob: or filesystem: URL like "blob:http://origin/blob-guid" // then the inner origin will be returned (unlike with `url::SchemeHostPort`) // 5) data: URLs will be correctly be translated into opaque origins, but the // precursor origin will be lost (unlike with `url::Resolve`). url::Origin origin = url::Origin::Create(url); // WARNING: `url::SchemeHostPort(url)` will *mechanically* extract the scheme, // host, and port of the URL, discarding other parts of the URL. This may have // unexpected results when: // 1) `url` is "about:blank", or "about:srcdoc" // 2) `url` comes from a sandboxed frame, i.e. when an opaque origin is expected // 3) `url` is a data: URL, i.e. when an opaque origin is expected // 4) `url` is a blob: or filesystem: URL like "blob:http://origin/blob-guid" // (the inner origin will *not* be returned - unlike `url::Origin::Create`) url::SchemeHostPort scheme_host_port = url::SchemeHostPort(url); // `url::Origin::Resolve` should work okay when: // 1) `url` is "about:blank", or "about:srcdoc" // 2) `url` comes from a sandboxed frame (i.e. when `base_origin` is opaque) // 3) `url` is a data: URL (i.e. propagating precursor of `base_origin`) // 4) `url` is a blob: or filesystem: URL like "blob:http://origin/blob-guid" // // WARNING: It is simpler and more robust to just use `GetLastCommittedOrigin` // (instead of combining `GetLastCommittedOrigin` and `GetLastCommittedURL` // using `url::Origin::Resolve`). // WARNING: `url::Origin::Resolve` is unaware of `base_url_for_data_url`. const url::Origin& base_origin = ... url::Origin origin = url::Origin::Resolve(url, base_origin);