Isolated Origins

A Collection of Interesting Ideas,

Version History:
https://github.com/mikewest/isolation/commits/master/index.src.html
Issue Tracking:
GitHub
Inline In Spec
Editors:
Emily Stark
Tanvi Vyas
David Ross
Mike West
Joel Weinberger
Participate:
File an issue (open issues)

Abstract

This specification defines an isolation policy that aims to protect an origin from malicious web content.

1. Introduction

Authors of security-critical applications want the web’s low-friction install process, its linkability, and its cross-platform nature, but are understandably nervous about hosting very powerful applications on the web alongside malicious content that can attack in any number of ways. For example, malicious content can:

It may not make sense to describe Isolation as mitigating phishing scenarios like this. It may indeed do so, but it’s not the primary goal.

Security-critical applications should be able to run in a browser with a degree of isolation that mitigates these attacks. This specification defines an isolation mechanism that an origin can opt in to, thereby reducing its exposure to other web content. Developers responsible for security-critical web applications can choose to trade away some of the features of being on the open web (such as full linkability) in exchange for better protection from malicious web content.

Given that a navigation manager enables linkability, it may not make sense to suggest there is a necessary tradeoff, at least in this respect.

1.1. Threat Model

We consider a security-critical application, very-important.com, whose developers want to isolate it from regular web content like evil.com. We assume that very-important.com is a large, complicated site with many developers, some of whom occasionally make mistakes, such as accidentally opening up a reflected XSS vulnerability. We also assume that the user does not know that evil.com is evil, and also that the user is not necessarily a power user; thus the user does not necessarily take precautions such as using evil.com and very-important.com in separate profiles or browsers. In our threat model, evil.com might try to attack very-important.com in a number of ways which this document aims to address:

  1. evil.com might cause the user’s browser to send a request to very-important.com that exploits a cross-site scripting (XSS) or cross-site request forgery (CSRF) vulnerability. Such vulnerabilities might be triggered by navigational requests (via iframe or open()), or by subresource requests (via img, etc).

  2. very-important.com might open a link to evil.com (for example, user-generated content could include an auto-linked reference to that origin, or a content write posted a link to evil.com without knowing that it is evil). This allows evil.com to obtain a reference to the very-important.com window via the window.opener attribute, which opens up communication channels (postMessage(), frame counting and traversal, navigation of the very-important.com window, etc.) that very-important.com might not be expecting.

  3. Likewise, evil.com can obtain such a reference via open().

  4. evil.com might exploit a vulnerability in the browser itself (UXSS) to gain access to very-important.com data and cookies.

    Note: The mechanism proposed in this document does not aim to give hard guarantees about protection from UXSS, but does hope to mitigate some of the risks on a best-effort basis.

  5. evil.com might be able to extract data from very-important.com by loading its resources or framing its content. Extraction techniques could range from exploitation of overly-broad CORS headers, to timing attacks like [HEIST], [PIXEL-PERFECT], etc.

Maybe mention that this would be facilited by ambient authority?

  1. very-important.com might embed resources from other origins (e.g., investments-r-us.biz), where the user becomes authenticated with investments-r-us.biz by authenticating with very-important.com. evil.com might then be able to extract very-important.com user data from investments-r-us.biz, even if it can’t attack very-important.com directly.

  2. evil.com and very-important.com might in fact be evil.example.com and very-important.example.com, in which case:

    1. evil.example.com might try to set a cookie for all of example.com in hopes that it can fix a session or CSRF token for the user on very-important.example.com.

    2. evil.example.com might take advantage of very-important.example.com's (ill-advised) loosening of the same-origin policy via Document's domain attribute.

1.2. Mitigation Strategy

To address the threats above, this document details an origin-wide isolation mechanism that aims to break the communication channels between very-important.com and evil.com. When very-important.com opts-in to this mechanism, the user agent will enforce the following:

  1. Resources from very-important.com may not be framed by cross-origin contexts. That is, the user agent will act as though Content-Security-Policy: frame-ancestors 'self' is delivered with each resource. This prevents evil.com from exploiting attacks that require control over very-important.com's browsing context ([PIXEL-PERFECT], as well as straightforward clickjacking), or access to very-important.com's Window (via contentWindow).

  2. Cross-origin resources framed by very-important.com are not given access to window.top or window.parent (those accessors will return null). This prevents evil.com from exploiting attacks which require access to very-important.com's Window, or navigating the user to an unexpected URL to replace very-important.com in the top-level browsing context.

  3. When very-important.com opens a new, cross-origin window (via open(), <a target="_blank">...</a>, etc.), the new window will disown its opener, and the call to open() will return null. That is, the user agent will act as though noopener is specified on outgoing links and open() calls.

    Likewise, when very-important.com is opened from a cross-origin window, it will disown its opener, and the return value of open() in the opener context will be null.

  4. All cookies set by very-important.com will be forced to be strict same-site cookies. This prevents evil.com from initiating authenticated requests to very-important.com. Further, all cookies set on very-important.com (including cookies set by responses to cross-origin requests) will be double-keyed and not sent on requests that occur outside the isolated context. This prevents evil.com from attacking ambient authority granted to very-important.com's cross-site dependencies by virtue of being embedded in very-important.com.

  5. Navigation into the isolated origin will be regulated by a navigation manager. Code from the isolated origin will get to validate each navigation before allowing it to proceed.

  6. The user agent should load example.com into a separate process from other web content.

    Note: This is not a firm guarantee (especially since not all browsers implement per-site process isolation at all), but rather a best-effort attempt to mitigate the risks of UXSS bugs.

2. Key Concepts

An isolated origin is an origin that has opted in to isolate itself from other origins on the web, using the mechanisms defined in this specification.

User agents have an isolated origin store, which is a list of isolated origins.

When asked if an origin is isolated, an isolated origin store will return true if the given origin appears in its list, and false otherwise.

Expand to have an expiration time for each isolated origin in the store.

3. Opting into isolation

Isolated origins are defined by an isolation HTTP response header. The syntax for the name and value of the header are described by the following ABNF grammar [RFC5234]:

"Isolation:" *WSP "1" *WSP

Add a max-age

§5.3.2 Processing isolation headers describes how the isolation header is processed.

the isolate-me HTTP header needs to be sent and/or processed before the Set-Cookie header...

An isolated origin can use a service worker to perform security checks on navigations. By default, every navigation to an isolated origin fails, unless the origin has a service worker which explicitly allows it.

§5.3.1 Navigation checks and §5.1.5 Process a navigate response describe how the Fetch and HTML specs are modified to fail navigations to an isolated origin unless a service worker has performed security checks on them.

5. Integrations

5.1. Integration with HTML

5.1.1. Origin

The HTML concept of origin should be expanded to contain a boolean isolated getter. This getter returns true if the origin is isolated and false otherwise.

The same origin check should be modified to return false if A is isolated but B is not, or vice versa.

Justify why the isolated flag does not need to be serialized

5.1.2. Cross-origin framing of isolated origins

Isolated origins should not be framed by cross-origin content. Step 1 of Process a navigate response should be modified to call §6.1 Should navigation response in target be blocked?.

5.1.3. Disowning isolated openers

When an isolated origin opens a new window to a different origin, that origin should not be able to manipulate the isolated origin via the window.opener attribute.

Initializing a new Document object should be modified to call §6.2 Disown an isolated opener on browsingContext and the response used to generate the document.

5.1.4. Removing cross-origin subframe references

When an isolated origin embeds cross-origin subframes, those subframes should not be able to obtain references to the isolated origin’s window via window.top or window.parent.

The window.top attribute algorithm should be modified to return null if context's top-level browsing context’s active document’s origin is an isolated origin.

Similarly, the window.parent attribute algorithm should be modified to return null if context's top-level browsing context’s active document’s origin is an isolated origin.

5.1.5. Process a navigate response

Process a navigate response should be modified to fail a navigation to an isolated origin if it has not been explicitly allowed by a service worker for that origin. Specifically, Step 1 should be modified to include the condition:

5.2. Integration with Cookies

This section defines modifications to [COOKIES] to support isolated origins.

5.2.1. Forcing cookies to be same-site

Forcing cookies from isolated origins to be same-site means that an attacker cannot initiate an authenticated request from a victim’s browser to an isolated origin.

When receiving a cookie string on a request whose initiator’s origin is isolated, if the request’s origin is same origin with the initiator’s origin, Section 5.3 should be modified to set the cookie’s samesite-flag field to "Strict".

5.2.2. Double-keyed storage

When a cookie is set on a request for which the top-level document is an isolated origin, the cookie should be double-keyed, such that the cookie is only sent on requests initiated by contexts in which the top-level document is the same isolated origin. This prevents attackers from attacking ambient authority that an isolated origin’s cross-site dependencies obtain by virtue of being embedded in the isolated origin.

This section defines modifications to [COOKIES] to support these double-keyed cookies.

5.2.2.1. Storage model

The storage model of [COOKIES] should be updated to keep track of when cookies are set in a top-level isolated origin as follows. Section 5.3 of [COOKIES] should be modified to store an additional isolated-origin field for each cookie. When processing a cookie, if the request has a non-null client, then let top origin be the origin of the request’s client’s responsible browsing context’s top-level browsing context’s active Document. If top origin is an isolated origin, then then the user agent should set the isolated-origin cookie field to top origin. Otherwise, the user agent should set the isolated-origin cookie field to the empty string.

define this section for Worker-based requests

[COOKIES] should be updated to ensure that cookies that were set on an isolated origin are not sent in other contexts outside that origin. In other words, Section 5.4 of [COOKIES] should be modified to add the following to the list of requirements in step 1:

these cookie changes don’t prevent all session fixation attacks. If a user has never visited victim.example.com before, evil.example.com can set a cookie for .example.com, which will be sent on the request when the user first navigates to victim.example.com. The isolated origin can mitigate this by using __Host- cookies for sensitive cookies. Maybe isolated origins should be required to use __Host- on all cookies.

5.3. Integration with Fetch

5.3.1. Navigation checks

The Fetch spec should be modified to give request a boolean allow isolated navigation flag, which is false by default. This flag is checked on navigations to isolated origins in §5.1.5 Process a navigate response.

The Request class should be modified to have an allowIsolatedNavigation() method, which, when invoked, must run these steps:

  1. Let origin be current settings object’s origin.

  2. If origin is not same origin with request’s current url’s origin, then abort these steps.

    should this throw an exception instead?

  3. Set request’s allow isolated navigation flag to true.

NOTE: A service worker or a consumer of the Fetch API must call allowIsolatedNavigation() on a Request in order for a navigation to an isolated origin to be allowed.

Does this allow for navigation requests to redirect to isolated origins? Do we want it to?

5.3.2. Processing isolation headers

Fetch should be updated to call §6.3 Isolate an origin on response after Step 13 of HTTP-network fetch.

6. Algorithms

6.1. Should navigation response in target be blocked?

This algorithm is used to block cross-origin framing of isolated origins. Given a response (navigation response) and a browsing context (target), this algorithm returns "Blocked" if navigation response is from an isolated origin and one or more of the ancestors of target is cross-origin.

  1. If target is not a nested browsing context, return "Allowed".

  2. If navigation response’s url’s origin is not an isolated origin, then return "Allowed".

  3. Let current be target.

  4. Let navigation origin be a copy of navigation response’s url’s origin. Set navigation origin’s isolated flag to true.

  5. While current has a parent browsing context (parent):

    1. Set current to parent.

    2. Let origin be current’s active document’s relevant settings object’s origin.

    3. If origin is not same origin with navigation origin, return "Blocked".

  6. Return "Allowed".

6.2. Disown an isolated opener

Given a browsing context (browsingContext) and a response (response) used to generate a document, this algorithm disowns browsingContext’s opener if the opener is an isolated origin.

  1. If browsingContext does not have an opener browsing context, then abort these steps.

  2. Let openedOrigin be a copy of response’s url’s origin.

  3. Let openerOrigin be browsingContext’s opener browsing context’s active document’s relevant settings object’s origin.

  4. If openerOrigin is not an isolated origin, abort these steps.

  5. If openedOrigin is same origin with openerOrigin, then abort these steps.

  6. browsingContext should disown its opener.

6.3. Isolate an origin

This algorithm is called from HTTP-network fetch to process an isolation header on a response response.

  1. If extracting header list values given isolation and response’s header list returns null, then abort these steps.

  2. Let origin be response’s url’s origin.

  3. If origin is not an isolated origin, set request’s allow isolated navigation flag to true.

NOTE: This step ensures that the first navigation to an isolated origin is allowed.

  1. Add origin to the user agent’s isolated origin store.

parse and process max-age

7. Security Considerations

8. Privacy Considerations

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[COOKIES]
A. Barth. HTTP State Management Mechanism. April 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6265
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC5234]
D. Crocker, Ed.; P. Overell. Augmented BNF for Syntax Specifications: ABNF. January 2008. Internet Standard. URL: https://tools.ietf.org/html/rfc5234
[SERVICE-WORKERS-1]
Alex Russell; et al. Service Workers 1. URL: https://w3c.github.io/ServiceWorker/
[WHATWG-DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[WHATWG-URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/

Issues Index

It may not make sense to describe Isolation as mitigating phishing scenarios like this. It may indeed do so, but it’s not the primary goal.
Given that a navigation manager enables linkability, it may not make sense to suggest there is a necessary tradeoff, at least in this respect.
Maybe mention that this would be facilited by ambient authority?
Expand to have an expiration time for each isolated origin in the store.
Add a max-age
the isolate-me HTTP header needs to be sent and/or processed before the Set-Cookie header...
Justify why the isolated flag does not need to be serialized
define this section for Worker-based requests
these cookie changes don’t prevent all session fixation attacks. If a user has never visited victim.example.com before, evil.example.com can set a cookie for .example.com, which will be sent on the request when the user first navigates to victim.example.com. The isolated origin can mitigate this by using __Host- cookies for sensitive cookies. Maybe isolated origins should be required to use __Host- on all cookies.
should this throw an exception instead?
Does this allow for navigation requests to redirect to isolated origins? Do we want it to?
parse and process max-age