Features/Platform/Iframe Sandbox

From MozillaWiki
Jump to: navigation, search
Please use "Edit with form" above to edit this page.

Status

Iframe Sandbox
Stage Landed
Status Complete
Release target Firefox 17
Health OK
Status note landed in FF17 - some followup work remains

Team

Product manager Lucas Adamski
Directly Responsible Individual Ian Melven
Lead engineer Ian Melven
Security lead Curtis Koenig
Privacy lead Sid Stamm
Localization lead `
Accessibility lead `
QA lead `
UX lead `
Product marketing lead `
Operations lead `
Additional members `

Open issues/risks

`

Stage 1: Definition

1. Feature overview

The HTML5 spec specifies a new attribute for the IFRAME element, "sandbox", see http://dev.w3.org/html5/spec/the-iframe-element.html#attr-iframe-sandbox. See also bug 341604 "Implement HTML5 sandbox attribute for IFRAMEs" and bug 671389 "Implement CSP sandbox directive"

2. Users & use cases

Users are web developers looking for a way to isolate content on their site and prevent it from having its default same origin privileges, ability to execute scripts and other normally granted abilities. The HTML5 spec specifies some modifying attributes that can grant permissions such as same origin , executing scripts, navigating the top window and submitting forms, etc. There are other abilities which are always removed in a sandboxed document that cannot be granted.

3. Dependencies

`

4. Requirements

This feature should be designed and implemented in a way that makes it usable for also implementing the sandboxing required to support the CSP (Content Security Policy) sandbox value also.

This feature requires a comprehensive test suite, as automated as possible for inclusion in the Firefox unit tests - Boris Zbarsky has suggested we also submit this test suite to the W3C for inclusion in their HTML5 test suite.

Non-goals

  • Providing sandboxing above and beyond what's described in the HTML5 spec
  • implementing the IFRAME seamless attribute and interactions between it the sandbox attribute.
  • implementing @sandbox on <object> - this was discussed on the whatwg list, currently we don't want to do this, since the meaning of sandbox on <object> is confusing - it would apply in some contexts and not others
  • implementing @sandbox on <frame> - this was discussed on the whatwg list and @sandbox for <frame> will not be implemented at the current time (this matches at least one other implementation)
  • implementing @sandbox on <xul:iframe/browser/editor> - the current implementation shouldn't prevent this enhancement from being implemented but there are no plans to implement this at the current time

Stage 2: Design

5. Functional specification

An IFRAME with the sandbox attribute (and its various modifying attributes) should behave as outlined in the HTML5 spec. See W3C Working Draft at http://www.w3.org/TR/html5/the-iframe-element.html#the-iframe-element and W3C Editor's Draft at http://dev.w3.org/html5/spec/Overview.html#the-iframe-element. This feature attempts to be compatible with the CSP sandbox directive (see https://wiki.mozilla.org/Security/CSP/Sandbox) by establishing infrastructure where CSP only needs to set the sandbox flags on content documents to have them sandboxed as intended.

6. User experience design

`

Stage 3: Planning

7. Implementation plan

  • The general approach for removing same-origin privileges is to give a sandboxed IFRAME a null principal to remove its normal domain/principal. This removes its same origin privileges unless allow-same-origin is specified as part of the sandbox attribute. In some case, there are additional checks that need to be added to the code to see if a document is sandboxed in a way that would prevent an operation from occurring.
  • We will use nsDocShell::SetAllowPlugins(false) to prevent plugins being loaded by a sandboxed IFRAME
  • We will create the flags as described in the HTML5 spec's description of the IFRAME sandbox attribute on both the docshell and the document when it is loaded

content/base/src/nsSandboxFlags.h contains :

+  /**
+   * This flag prevents content from navigating browsing contexts other than
+   * the sandboxed browsing context itself (or browsing contexts further
+   * nested inside it), and the top-level browsing context.
+   */
+  const unsigned long SANDBOXED_NAVIGATION  = 0x1;
+
+  /**
+   * This flag prevents content from navigating their top-level browsing
+   * context.
+   */
+  const unsigned long SANDBOXED_TOPLEVEL_NAVIGATION = 0x2;
+
+  /**
+   * This flag prevents content from instantiating plugins, whether using the
+   * embed element, the object element, the applet element, or through
+   * navigation of a nested browsing context, unless those plugins can be
+   * secured.
+   */
+  const unsigned long SANDBOXED_PLUGINS = 0x4;
+
+  /**
+   * This flag forces content into a unique 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.
+   */
+  const unsigned long SANDBOXED_ORIGIN = 0x8;
+
+  /**
+   * This flag blocks form submission.
+   */
+  const unsigned long SANDBOXED_FORMS = 0x10;
+
+  /**
+   * This flag blocks script execution.
+   */
+  const unsigned long SANDBOXED_SCRIPTS = 0x20;
    • when the sandbox attribute on an IFRAME element is modified, we will change the flags on the docshell but not the document - the document must be reloaded for the changed flags on the docshell to take effect
      • we will implement this using nsHTMLIFrameElement::AfterSetAttr,
    • the document needs to keep the exact set of flags assigned at load time (these are immutable - changing sandbox attributes does NOT dynamically affect already loaded content)
    • sandbox flags for a document are set based on the sandbox flags of its parent document and the sandbox flags of the embedding frame (stored in the docshell)
  • sandboxed IFRAME's need to block access (read and write) to document.cookie

and local and session storage unless the allow-same-origin keyword is specified

  • sandboxed IFRAME's are also supposed to block access to content automatically doing something, the examples given automatically playing a video or automatically focusing a form control (unless allow-scripts is specified since scripts can do this anyways) - while disabling JS will take care of many of these cases, HTML5 video autoplay may need to be handled separately and there could be many other edge cases here as well ! - i would prefer to address this in a follow-up patch/bug as playing video or auto focusing a text field doesn't IMO diminish the security benefits provided by landing the rest of the functionality as defined in the HTML5 spec
  • nsFrameLoader will be modified to assign the null principal to a sandboxed IFRAME (if allow-same-origin is not specified)
    • this also requires modifying surrounding code to be able to force an owner to be set on the loading channel.
    • we may be able to implement both cases in one place if we do the null principal assignment at a low enough level in the docshell loading code
    • The nsFrameLoader will check if its owner content has the sandbox attribute set and is an nsHTMLIFrameElement to determine whether to sandbox the frame being loaded (again, if the allow-same-domain modifier isn't present in the sandbox attribute)
  • when we support the CSP sandbox directive, similar logic to that in nsFrameLoader will need to be implemented for the loaders for other CSP-protectable resources
  • for CSP sandbox, the flags will only be stored on the document itself - when content is navigated to, the CSP sandbox flags won't be persisted (unless the new content also specifies a CSP sandbox directive)
  • the HTML5 spec provides examples of how to apply flags with nested IFRAMEs, abarth has proposed that if both CSP and IFRAME sandbox can apply to content, the algorithm used in these example should be used to merge the policies which sounds reasonable
  • Disabling Javascript uses the same script choke points as CSP to maximize the functionality available in a sandboxed document while still not allowing the document to load a remote script or execute inline script.
  • After discussion, we allow workers to be loaded inside a sandboxed document with 'allow-scripts' (but without 'allow-same-origin') from a data: URL or a blob URL created by the same sandboxed document creating the worker. This requires modifying either worker code or CheckMayLoad() code most likely.
  • After discussion, although the sandbox attribute is specified as DOMSettableTokenList in the HTML5 spec, this implementation implements it as a DOMString.

8. Reviews

Security review

This feature will definitely need a full security review from the Security Assurance team. I've posted this feature page on dev.security and updated the bug with decisions and implementation plans as implementation has proceeded. Before the security review I will post again to dev.security and encourage review of this feature page and the HTML5 iframe sandbox spec.

Privacy review

`

Localization review

`

Accessibility

`

Quality Assurance review

We will need a test suite for this feature. Microsoft has released test cases for sandboxing publically that have been submitted to the W3C for inclusion in the HTML5 test suite. We will definitely want to compare our implementation to other browsers' implementation for consistency etc. and address inconsistencies via suggested modifications to the HTML5 spec and discussion on the whatwg list. Boris Zbarsky has suggested submitting our sandbox test suite to the W3C also.

A mochitest test suite has been written to provide consistent automated testing for this feature.

Operations review

`

Stage 4: Development

9. Implementation

See https://bugzilla.mozilla.org/show_bug.cgi?id=341604 for a patch that attempts to implement HTML5 iframe sandbox.

There's an set of tests for various pieces of functionality in that bug as well.

Please see the bug for updates to current patches and iteration based on feedback/review.

Stage 5: Release

10. Landing criteria

  • Needs a test suite - DONE
  • Needs to be compared against other implementations and public test suites for consistency - DONE
  • Needs a full security review - DONE
The given value "* The general approach for removing same-origin privileges is to give a sandboxed IFRAME a null principal to remove its normal domain/principal. This removes its same origin privileges unless allow-same-origin is specified as part of the sandbox attribute. In some case, there are additional checks that need to be added to the code to see if a document is sandboxed in a way that would prevent an operation from occurring.
  • We will use nsDocShell::SetAllowPlugins(false) to prevent plugins being loaded by a sandboxed IFRAME
  • We will create the flags as described in the HTML5 spec's description of the IFRAME sandbox attribute on both the docshell and the document when it is loaded

content/base/src/nsSandboxFlags.h contains :

+  /**
+   * This flag prevents content from navigating browsing contexts other than
+   * the sandboxed browsing context itself (or browsing contexts further
+   * nested inside it), and the top-level browsing context.
+   */
+  const unsigned long SANDBOXED_NAVIGATION  = 0x1;
+
+  /**
+   * This flag prevents content from navigating their top-level browsing
+   * context.
+   */
+  const unsigned long SANDBOXED_TOPLEVEL_NAVIGATION = 0x2;
+
+  /**
+   * This flag prevents content from instantiating plugins, whether using the
+   * embed element, the object element, the applet element, or through
+   * navigation of a nested browsing context, unless those plugins can be
+   * secured.
+   */
+  const unsigned long SANDBOXED_PLUGINS = 0x4;
+
+  /**
+   * This flag forces content into a unique 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.
+   */
+  const unsigned long SANDBOXED_ORIGIN = 0x8;
+
+  /**
+   * This flag blocks form submission.
+   */
+  const unsigned long SANDBOXED_FORMS = 0x10;
+
+  /**
+   * This flag blocks script execution.
+   */
+  const unsigned long SANDBOXED_SCRIPTS = 0x20;
    • when the sandbox attribute on an IFRAME element is modified, we will change the flags on the docshell but not the document - the document must be reloaded for the changed flags on the docshell to take effect
      • we will implement this using nsHTMLIFrameElement::AfterSetAttr,
    • the document needs to keep the exact set of flags assigned at load time (these are immutable - changing sandbox attributes does NOT dynamically affect already loaded content)
    • sandbox flags for a document are set based on the sandbox flags of its parent document and the sandbox flags of the embedding frame (stored in the docshell)
  • sandboxed IFRAME's need to block access (read and write) to document.cookie

and local and session storage unless the allow-same-origin keyword is specified

  • sandboxed IFRAME's are also supposed to block access to content automatically doing something, the examples given automatically playing a video or automatically focusing a form control (unless allow-scripts is specified since scripts can do this anyways) - while disabling JS will take care of many of these cases, HTML5 video autoplay may need to be handled separately and there could be many other edge cases here as well ! - i would prefer to address this in a follow-up patch/bug as playing video or auto focusing a text field doesn't IMO diminish the security benefits provided by landing the rest of the functionality as defined in the HTML5 spec
  • nsFrameLoader will be modified to assign the null principal to a sandboxed IFRAME (if allow-same-origin is not specified)
    • this also requires modifying surrounding code to be able to force an owner to be set on the loading channel.
    • we may be able to implement both cases in one place if we do the null principal assignment at a low enough level in the docshell loading code
    • The nsFrameLoader will check if its owner content has the sandbox attribute set and is an nsHTMLIFrameElement to determine whether to sandbox the frame being loaded (again, if the allow-same-domain modifier isn't present in the sandbox attribute)
  • when we support the CSP sandbox directive, similar logic to that in nsFrameLoader will need to be implemented for the loaders for other CSP-protectable resources
  • for CSP sandbox, the flags will only be stored on the document itself - when content is navigated to, the CSP sandbox flags won't be persisted (unless the new content also specifies a CSP sandbox directive)
  • the HTML5 spec provides examples of how to apply flags with nested IFRAMEs, abarth has proposed that if both CSP and IFRAME sandbox can apply to content, the algorithm used in these example should be used to merge the policies which sounds reasonable
  • Disabling Javascript uses the same script choke points as CSP to maximize the functionality available in a sandboxed document while still not allowing the document to load a remote script or execute inline script.
  • After discussion, we allow workers to be loaded inside a sandboxed document with 'allow-scripts' (but without 'allow-same-origin') from a data: URL or a blob URL created by the same sandboxed document creating the worker. This requires modifying either worker code or CheckMayLoad() code most likely.
  • After discussion, although the sandbox attribute is specified as DOMSettableTokenList in the HTML5 spec, this implementation implements it as a DOMString." contains strip markers and therefore it cannot be parsed sufficiently.

Feature details

Priority P1
Rank 999
Theme / Goal Security Leadership
Roadmap Security
Secondary roadmap Platform
Feature list `
Project `
Engineering team Security

Team status notes

  status notes
Products ` `
Engineering Complete Landed in FF17 - there are some followups.
Security ` `
Privacy ` `
Localization ` `
Accessibility ` `
Quality assurance ` `
User experience ` `
Product marketing ` `
Operations ` `