Edition for Web Developers — Last Updated 5 December 2024
Origins are the fundamental currency of the web's security model. Two actors in the web platform that share an origin are assumed to trust each other and to have the same authority. Actors with differing origins are considered potentially hostile versus each other, and are isolated from each other to varying degrees.
For example, if Example Bank's web site, hosted at bank.example.com
, tries to examine the DOM of Example Charity's web site, hosted
at charity.example.org
, a "SecurityError
"
DOMException
will be raised.
An origin is one of the following:
An internal value, with no serialization it can be recreated from (it is serialized as
"null
" per serialization of an origin), for which the only
meaningful operation is testing for equality.
A tuple consists of:
Origins can be shared, e.g., among multiple
Document
objects. Furthermore, origins are generally
immutable. Only the domain of a tuple origin can be changed, and only through the document.domain
API.
The serialization of ("https
", "xn--maraa-rta.example
", null, null) is "https://xn--maraa-rta.example
".
The following table shows examples of when two tuple origins are same origin and same origin-domain.
A | B | same origin | same origin-domain |
---|---|---|---|
("https ", "example.org ", null, null)
| ("https ", "example.org ", null, null)
| ✅ | ✅ |
("https ", "example.org ", 314, null)
| ("https ", "example.org ", 420, null)
| ❌ | ❌ |
("https ", "example.org ", 314, "example.org ")
| ("https ", "example.org ", 420, "example.org ")
| ❌ | ✅ |
("https ", "example.org ", null, null)
| ("https ", "example.org ", null, "example.org ")
| ✅ | ❌ |
("https ", "example.org ", null, "example.org ")
| ("http ", "example.org ", null, "example.org ")
| ❌ | ❌ |
A scheme-and-host is a tuple of a scheme (an ASCII string) and a host (a host).
A site is an opaque origin or a scheme-and-host.
Unlike the same origin and same origin-domain concepts, for schemelessly same site and same site, the port and domain components are ignored.
For the reasons explained in URL, the same site and schemelessly same site concepts should be avoided when possible, in favor of same origin checks.
The following table shows examples of when two tuple origins are schemelessly same site and same site.
Given that wildlife.museum
, museum
, and com
are public suffixes and that example.com
is not:
A | B | schemelessly same site | same site |
---|---|---|---|
("https ", "example.com ")
| ("https ", "sub.example.com ")
| ✅ | ✅ |
("https ", "example.com ")
| ("https ", "sub.other.example.com ")
| ✅ | ✅ |
("https ", "example.com ")
| ("http ", "non-secure.example.com ")
| ✅ | ❌ |
("https ", "r.wildlife.museum ")
| ("https ", "sub.r.wildlife.museum ")
| ✅ | ✅ |
("https ", "r.wildlife.museum ")
| ("https ", "sub.other.r.wildlife.museum ")
| ✅ | ✅ |
("https ", "r.wildlife.museum ")
| ("https ", "other.wildlife.museum ")
| ❌ | ❌ |
("https ", "r.wildlife.museum ")
| ("https ", "wildlife.museum ")
| ❌ | ❌ |
("https ", "wildlife.museum ")
| ("https ", "wildlife.museum ")
| ✅ | ✅ |
("https ", "example.com ")
| ("https ", "example.com. ")
| ❌ | ❌ |
(Here we have omitted the port and domain components since they are not considered.)
document.domain [ = domain ]
Returns the current domain used for security checks.
Can be set to a value that removes subdomains, to change the origin's domain to allow pages on other subdomains of the same domain (if they do the same thing) to access each other. This enables pages on different hosts of a domain to synchronously access each other's DOMs.
In sandboxed iframe
s, Document
s with opaque origins, and Document
s without a browsing context, the setter will
throw a "SecurityError
" exception. In cases where crossOriginIsolated
or originAgentCluster
return true, the setter will do
nothing.
Avoid using the document.domain
setter. It
undermines the security protections provided by the same-origin policy. This is especially acute
when using shared hosting; for example, if an untrusted third party is able to host an HTTP
server at the same IP address but on a different port, then the same-origin protection that
normally protects two different sites on the same host will fail, as the ports are ignored when
comparing origins after the document.domain
setter has
been used.
Because of these security pitfalls, this feature is in the process of being removed from the web platform. (This is a long process that takes many years.)
Instead, use postMessage()
or
MessageChannel
objects to communicate across origins in a safe manner.
window.originAgentCluster
Returns true if this Window
belongs to an agent cluster which is
origin-keyed, in the manner described in
this section.
A Document
delivered over a secure context can request that it be
placed in an origin-keyed agent
cluster, by using the `Origin-Agent-Cluster
` HTTP
response header. This header is a structured header
whose value must be a boolean.
[STRUCTURED-FIELDS]
Values
that are not the structured header boolean
true value (i.e., `?1
`) will be ignored.
The consequences of using this header are that attempting to relax the same-origin
restriction using document.domain
will instead do
nothing, and it will not be possible to send WebAssembly.Module
objects to
cross-origin Document
s (even if they are same site). Behind the scenes,
this isolation can allow user agents to allocate implementation-specific resources corresponding
to agent clusters, such as processes or threads, more
efficiently.
Note that within a browsing context group, the
`Origin-Agent-Cluster
` header can never cause same-origin Document
objects to end up in different agent clusters, even if one
sends the header and the other doesn't.
This means that the originAgentCluster
getter can return false, even if the
header is set, if the header was omitted on a previously-loaded same-origin page in the same
browsing context group. Similarly, it can return true even when the header is not
set.
Document
s with an opaque
origin can be considered unconditionally origin-keyed; for them the header has no effect,
and the originAgentCluster
getter will always return
true.
Similarly, Document
s whose agent cluster's cross-origin isolation mode is not "none
" are automatically origin-keyed. The
`Origin-Agent-Cluster
` header might be useful as an additional hint to
implementations about resource allocation, since the `Cross-Origin-Opener-Policy
`
and `Cross-Origin-Embedder-Policy
` headers used to achieve cross-origin isolation
are more about ensuring that everything in the same address space opts in to being there. But
adding it would have no additional observable effects on author code.
An opener policy value allows a document which is navigated to in a top-level browsing context to force the creation of a new top-level browsing context, and a corresponding group. The possible values are:
unsafe-none
"This is the (current) default and means that the document will occupy the same top-level browsing context as its predecessor, unless that document specified a different opener policy.
same-origin-allow-popups
"This forces the creation of a new top-level browsing context for the document, unless its predecessor specified the same opener policy and they are same origin.
same-origin
"This behaves the same as "same-origin-allow-popups
", with the addition that
any auxiliary browsing context created needs to contain same origin
documents that also have the same opener policy or it will appear closed to the
opener.
same-origin-plus-COEP
"This behaves the same as "same-origin
", with the
addition that it sets the (new) top-level browsing context's group's cross-origin isolation
mode to one of "logical
" or "concrete
".
"same-origin-plus-COEP
" cannot
be directly set via the `Cross-Origin-Opener-Policy
` header, but results from a
combination of setting both `Cross-Origin-Opener-Policy: same-origin
` and a
`Cross-Origin-Embedder-Policy
` header whose value is compatible with
cross-origin isolation together.
noopener-allow-popups
"This forces the creation of a new top-level browsing context for the document, regardless of its predecessor.
While including a noopener-allow-popups
value severs the opener
relationship between the document on which it is applied and its opener, it does not create a
robust security boundary between those same-origin documents.
Other risks from same-origin applications include:
Same-origin requests fetching the document's content — could be mitigated through Fetch Metadata filtering. [FETCHMETADATA]
Same-origin framing - could be mitigated through X-Frame-Options
or CSP
frame-ancestors
.
JavaScript accessible cookies - can be mitigated by ensuring all cookies are httponly
.
localStorage
access to sensitive data.
Service worker installation.
postMessage
or BroadcastChannel
messaging that
exposes sensitive information.
Autofill which may not require user interaction for same-origin documents.
Developers using noopener-allow-popups
need to make sure that their sensitive applications don't rely on client-side features
accessible to other same-origin documents, e.g., localStorage
and other client-side storage APIs,
BroadcastChannel
and related same-origin communication mechanisms. They also need
to make sure that their server-side endpoints don't return sensitive data to non-navigation
requests, whose response content is accessible to same-origin
documents.
Headers/Cross-Origin-Opener-Policy
Support in all current engines.
A Document
's cross-origin opener
policy is derived from the `Cross-Origin-Opener-Policy
` and `Cross-Origin-Opener-Policy-Report-Only
` HTTP response headers.
These headers are structured headers whose value must
be a token. [STRUCTURED-FIELDS]
The valid token values are the opener policy values. The token may also have
attached parameters; of these, the "report-to
" parameter can have a valid URL
string identifying an appropriate reporting endpoint. [REPORTING]
User agents will ignore this header if it contains an invalid value. Likewise, user agents will ignore this header if the value cannot be parsed as a token.
Headers/Cross-Origin-Embedder-Policy
Support in all current engines.
An embedder policy value is one of three strings that controls the fetching of cross-origin resources without explicit permission from resource owners.
unsafe-none
"This is the default value. When this value is used, cross-origin resources can be fetched
without giving explicit permission through the CORS protocol or the
`Cross-Origin-Resource-Policy
` header.
require-corp
"When this value is used, fetching cross-origin resources requires the server's
explicit permission through the CORS protocol or the
`Cross-Origin-Resource-Policy
` header.
credentialless
"When this value is used, fetching cross-origin no-CORS resources omits credentials. In
exchange, an explicit `Cross-Origin-Resource-Policy
` header is not required. Other
requests sent with credentials require the server's explicit permission through the CORS
protocol or the `Cross-Origin-Resource-Policy
` header.
Before supporting "credentialless
", implementers are
strongly encouraged to support both:
Otherwise, it would allow attackers to leverage the client's network position to read non public resources, using the cross-origin isolated capability.
An embedder policy value is compatible with cross-origin isolation if
it is "credentialless
" or "require-corp
".
The `Cross-Origin-Embedder-Policy
` and
`Cross-Origin-Embedder-Policy-Report-Only
` HTTP response
headers allow a server to declare an embedder policy for an environment
settings object. These headers are structured
headers whose values must be token.
[STRUCTURED-FIELDS]
The valid token values are the embedder policy values. The token may also have attached parameters; of these, the "report-to
" parameter can have a valid URL
string identifying an appropriate reporting endpoint. [REPORTING]
The processing model fails open (by defaulting
to "unsafe-none
") in the presence of a header that cannot
be parsed as a token. This includes inadvertent lists created by combining multiple instances of
the `Cross-Origin-Embedder-Policy
` header present in a given response:
`Cross-Origin-Embedder-Policy ` | Final embedder policy value |
---|---|
No header delivered | "unsafe-none " |
`require-corp ` | "require-corp " |
`unknown-value ` | "unsafe-none " |
`require-corp, unknown-value ` | "unsafe-none " |
`unknown-value, unknown-value ` | "unsafe-none " |
`unknown-value, require-corp ` | "unsafe-none " |
`require-corp, require-corp ` | "unsafe-none " |
(The same applies to `Cross-Origin-Embedder-Policy-Report-Only
`.)
A sandboxing flag set is a set of zero or more of the following flags, which are used to restrict the abilities that potentially untrusted resources have:
This flag prevents content from navigating browsing contexts other than the sandboxed browsing context itself (or browsing contexts further nested inside it), auxiliary browsing contexts (which are protected by the sandboxed auxiliary navigation browsing context flag defined next), and the top-level browsing context (which is protected by the sandboxed top-level navigation without user activation browsing context flag and sandboxed top-level navigation with user activation browsing context flag defined below).
If the sandboxed auxiliary navigation browsing context flag is not set, then in certain cases the restrictions nonetheless allow popups (new top-level browsing contexts) to be opened. These browsing contexts always have one permitted sandboxed navigator, set when the browsing context is created, which allows the browsing context that created them to actually navigate them. (Otherwise, the sandboxed navigation browsing context flag would prevent them from being navigated even if they were opened.)
This flag prevents content from creating new auxiliary browsing
contexts, e.g. using the target
attribute or
the window.open()
method.
This flag prevents content from navigating their top-level browsing context and prevents content from closing their top-level browsing context. It is consulted only when the sandboxed browsing context's active window does not have transient activation.
When the sandboxed top-level navigation without user activation browsing context flag is not set, content can navigate its top-level browsing context, but other browsing contexts are still protected by the sandboxed navigation browsing context flag and possibly the sandboxed auxiliary navigation browsing context flag.
This flag prevents content from navigating their top-level browsing context and prevents content from closing their top-level browsing context. It is consulted only when the sandboxed browsing context's active window has transient activation.
As with the sandboxed top-level navigation without user activation browsing context flag, this flag only affects the top-level browsing context; if it is not set, other browsing contexts might still be protected by other flags.
This flag forces content into an opaque origin, thus preventing it from accessing other content from the same origin.
This flag also prevents script from reading from or writing to the
document.cookie
IDL attribute, and blocks access
to localStorage
.
This flag blocks form submission.
This flag disables the Pointer Lock API. [POINTERLOCK]
This flag blocks script execution.
This flag blocks features that trigger automatically, such as automatically playing a video or automatically focusing a form control.
document.domain
browsing context flagThis flag prevents content from using the
document.domain
setter.
This flag prevents content from escaping the sandbox by ensuring that any auxiliary browsing context it creates inherits the content's active sandboxing flag set.
This flag prevents content from using any of the following features to produce modal dialogs:
This flag disables the ability to lock the screen orientation. [SCREENORIENTATION]
This flag disables the Presentation API. [PRESENTATION]
This flag prevents content from initiating or instantiating downloads, whether through downloading hyperlinks or through navigation that gets handled as a download.
This flag prevents navigations toward non fetch schemes from being handed off to external software.