Chrome's multi-process architecture
provides many benefits for speed, stability, and security. It allows web pages in unrelated tabs to run in parallel, and it allows users to continue using the browser and other tabs when a renderer process crashes. Because the renderer processes don't require direct access to disk, network, or devices, Chrome can also run them inside a restricted sandbox
. This limits the damage
that an attacker can cause if he exploits a vulnerability in the renderer, including making it difficult for the attacker to access the user's filesystem or devices, as well as privileged pages (e.g., settings or extensions) and pages in other profiles (e.g., Incognito mode).
However, there is still a large opportunity to use Chrome's sandbox for greater security benefits: isolating web sites from each other. Chrome currently makes an effort to place pages from different web sites in different renderer processes when possible, but due to compatibility constraints, there are many cases in which pages from different sites share a process (e.g., cross-site iframes). In these cases, we rely on the renderer process to enforce the Same Origin Policy and keep web sites isolated from each other.
This page describes our "site isolation" efforts to improve Chrome to use renderer processes as a security boundary between web sites, even in the presence of WebKit vulnerabilities. Our goal is to add support for a "site-per-process" policy that ensures each renderer process contains pages from at most one web site. The browser process can then give each renderer process limited access to cookies and other resources, based on that process's site.
For the "site-per-process" security policy, we assume that an attacker can convince the user to visit a page that exploits a vulnerability in the renderer process, allowing the attacker to run arbitrary code within the sandbox. We consider attackers that want to steal information or abuse privileges granted to other web sites.
Here, we use a precise definition for a site that we use as a principal: a page's site includes the scheme and registered domain name, including the public suffix, but ignoring subdomains, port, or path. We use sites instead of origins to avoid breaking compatibility with existing web pages that might modify their document.domain to communicate across subdomains.
We consider the following threats in scope for the proposed policy:
- Stealing cross-site cookies and HTML5 stored data. We can prevent a renderer process from receiving cookies or stored data from sites other than its own.
- Stealing cross-site HTML, XML, and JSON documents. Using MIME type and content sniffing, we can prevent a renderer process from loading cross-site documents. We cannot block all cross-site resources, however, because images, scripts, and other opaque files are permitted across sites.
- Stealing saved passwords. We can prevent a renderer process from receiving saved passwords from sites other than its own.
- Abusing permissions granted to another site. We can prevent a renderer process from using permissions such as geolocation that the user has granted to other sites.
- Compromising X-Frame-Options. We can prevent a renderer process from loading cross-site pages in iframes. This allows the browser process to decide if a given site can be loaded in an iframe or not based on X-Frame-Options headers.
We do not expect this policy to mitigate traditional cross-site attacks or attacks that occur within the page of a victim site, such as XSS, CSRF, XSSI, or clickjacking.
To support a site-per-process policy in a multi-process web browser, we need to identify the smallest unit that cannot be split across renderer processes. This is not actually a single page, but rather a group of pages from the same web site that have references to each other. Such pages have full script access to each other's content, and they must run on a single thread, not concurrently. These pages may span multiple frames or tabs, and they may come from multiple sub-domains of the same site.
The HTML spec refers to this group as a "unit of related similar-origin browsing contexts
." In Chrome, we refer to this as a SiteInstance
. All of the pages within a SiteInstance are allowed to script each other, and we must thus render them in the same process.
Note that a single tab might be navigated from one web site to another, and thus it may show different SiteInstances at different times. To support a site-per-process policy, a browser must be able to swap between renderer processes for these navigations.
In addition, top-level pages may contain iframes from different web sites. These iframes have their own security context and must be rendered in a process based on their own site, not the site of their parent frame.
Chrome's Current Status
As described on our Process Models
page, there are currently several cases in which Chrome will place pages from different sites in the same renderer process. This keeps Chrome compatible with pages that make script calls across windows, at least until the project tasks described below are completed. Some examples of cross-site pages that may share a process:
- Cross-site iframes are currently hosted in the same process as their parent page, because we don't yet have support for hosting them in a different process.
- Most renderer-initiated navigations (including link clicks, form submissions, and scripted navigations) are kept within the current process even if they cross a site boundary. This is because other windows in the same process may attempt to use postMessage or similar calls to interact with them.
- If too many renderer processes have been created, Chrome starts to reuse existing processes rather than creating new ones. This reduces memory overhead and avoid OS-specific limitations.
As a result of this progress, we have adopted a stricter security policy for certain types of pages, such privileged WebUI pages (like the Settings page). These pages are never allowed to share a process with regular web pages, even when navigating in a single tab. This is generally acceptable from a compatibility perspective because no scripting is expected between normal pages and WebUI pages.
To support a site-per-process policy in Chrome, we need to complete the tasks outlined below. These will ensure that cross-site navigations and script interactions will not break, despite having all pages from different sites in different processes.
- Cross-Process Navigations
Any navigation to a different web site requires a process swap in the current tab.
Status: This is in place for browser-initiated navigations, such as the Omnibox. It also works for renderer-initiated navigations between pages of different types, such as normal web pages, WebUI pages (e.g., settings), and app pages. With --site-per-process, we support cross-process navigations in all frames.
As mentioned above, some window and frame level interactions are allowed between pages from different sites. Common examples are postMessage, close, focus, blur, and assignments to window.location, notably excluding any access to page content. These interactions can generally be made asynchronous and can be implemented by passing messages to the appropriate renderer process.
Status: We currently support postMessage, close, focus, blur, and assignments to window.location between top-level windows in different processes. With --site-per-process, we have frame placeholders and are still adding support for these script calls. Remaining work tracked at http://crbug.com/128768.
- Out-of-Process iframes
Iframes have separate security contexts from their parent page, so cross-site iframes should be rendered in a different process from their parent. It is also important that an iframe that is from the same origin as a popup window shares a process with the popup window and not its own parent page. Our current plan is to render iframes in a separate RenderFrame composited into the correct visual location, much like plugins. This is the largest requirement for supporting site-per-process, as it involves a major architecture change to the Chrome and Blink codebases.
Status: We are currently implementing our Design Plans for Out-of-Process iframes. Tracked at http://crbug.com/99379.
- Improved Renderer Process Limit Policy
How to handle Chrome's renderer process limit remains an open question. Pending study of the performance implications, we have several options:
- We could choose to protect only a set of sensitive web sites, perhaps including those the user has logged into, or all HTTPS sites. These sites would never share a process with others, while other sites would be allowed to share with each other when the process limit is reached. (Caveat: isolating an HTTPS site without isolating its HTTP version would allow renderer exploits to view non-secure cookies for the site, as well as set secure cookies for the site, per RFC 6265.)
- We could repeal the process limit, particularly on clients with sufficient memory. This may cause OS-specific issues as resources are depleted, such as the inability to fork new processes.
- We could re-use processes according to some heuristics, allowing the security benefits of site isolation to degrade as more and more tabs are opened. This is less than ideal because the situation may not be evident or predictable to the user.
- When the limit is reached, other renderer processes may be killed and then restored when the user returns. This approach is already taken on many mobile devices, but it is less satisfactory on desktops, where there is more potential for data loss or visibly killed tabs.
- We could prevent the creation of new tabs until existing ones are closed. This limit is likely to annoy users without immediate benefits.
- Status: We are planning to initially protect only a set of opt-in, high-value sites. We will expand this set as resource usage permits.
- Browser Enforced Navigation Policy
Some of Chrome's policy logic for deciding when to perform a cross-process navigation currently runs in the renderer process. Since we assume renderer processes may be exploited, we need to move this logic to the browser process. Similarly, any attempt or report of a navigation to a cross-site page within a renderer should cause the browser to kill the renderer, under the assumption it has been exploited. It is worth noting that renderers are allowed to request many cross-site resources (such as scripts and images), but we can prevent them from receiving cross-site HTML, XML, and JSON documents (based on a combination of MIME type and content sniffing).
Status: Our Cross-Site Document Blocking Policy is posted and tracked at http://crbug.com/268640.
- Security Principal Refactoring
Any actions that the browser process takes on behalf of a renderer process should be associated with a security principal. This will allow the browser to enforce access control based on the principal, rather than a potentially inaccurate guess about the tab's current contents. This will help govern access to cookies or other data, as well as special APIs for extensions, apps, and WebUI pages.
Status: Proposed in http://crbug.com/109792, but on hold until a clearer need arises.
- Support for Cross-Process POST submissions
Chrome does not yet have support for cross-process navigations with POST submissions.
Status: Being tracked at http://crbug.com/101395.
For users eager to try site isolation before it is enabled by default, we have added two experimental command-line flags.
First, the --site-per-process flag starts to enforce the security policy described in this document. With this flag, Chrome 41 supports painting and simple input events for out-of-process iframes (such as this test page: http://csreis.github.io/tests/cross-site-iframe.html). This mode should only be used for experimentation and not normal browsing, as crashes are highly likely.
Second, the simpler --enable-strict-site-isolation flag forces a process swap on all cross-site navigations, even if this might disrupt valid script calls on some web sites. This mode also blocks access to cross-site cookies (unlike --site-per-process), which may cause compatibility issues with many web sites. Cross-origin iframes remain in their parent process, but because of cross-site cookie blocking, such pages are unauthenticated. This mode is effectively usable on most web sites today.
Site Isolation Summit 2015
Talks and discussion from January 2015
Site Isolation Overview
Chromium Changes for OOPIF