From 0d38cf2182ff1501e4030561583f373c67c40aa9 2014-03-25 23:57:27 From: MinRK Date: 2014-03-25 23:57:27 Subject: [PATCH] Merge Security Pull Request: security-doc Document the notebook security and trust model. --- diff --git a/docs/source/_templates/htmlnotebook.html b/docs/source/_templates/notebook_redirect.html similarity index 55% rename from docs/source/_templates/htmlnotebook.html rename to docs/source/_templates/notebook_redirect.html index 7133e91..0114404 100644 --- a/docs/source/_templates/htmlnotebook.html +++ b/docs/source/_templates/notebook_redirect.html @@ -1,9 +1,9 @@ - - Notebook page has move - + + Notebook docs have moved + -

The notebook page has moved to this link.

+

The notebook docs have moved here.

diff --git a/docs/source/conf.py b/docs/source/conf.py index 381c3f6..5bc7f0f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -164,7 +164,10 @@ html_last_updated_fmt = '%b %d, %Y' # Additional templates that should be rendered to pages, maps page names to # template names. html_additional_pages = { - 'interactive/htmlnotebook': 'htmlnotebook.html', + 'interactive/htmlnotebook': 'notebook_redirect.html', + 'interactive/notebook': 'notebook_redirect.html', + 'interactive/nbconvert': 'notebook_redirect.html', + 'interactive/public_server': 'notebook_redirect.html', } # If false, no module index is generated. diff --git a/docs/source/index.rst b/docs/source/index.rst index 2ddf644..72fc197 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -25,6 +25,7 @@ Contents whatsnew/index install/index interactive/index + notebook/index parallel/index config/index development/index diff --git a/docs/source/interactive/index.rst b/docs/source/interactive/index.rst index fd24a05..9a4ecdf 100644 --- a/docs/source/interactive/index.rst +++ b/docs/source/interactive/index.rst @@ -10,9 +10,7 @@ Using IPython for interactive work reference shell qtconsole - notebook - cm_keyboard - nbconvert - public_server +.. seealso:: + :doc:`/notebook/index` diff --git a/docs/source/interactive/cm_keyboard.rst b/docs/source/notebook/cm_keyboard.rst similarity index 100% rename from docs/source/interactive/cm_keyboard.rst rename to docs/source/notebook/cm_keyboard.rst diff --git a/docs/source/notebook/index.rst b/docs/source/notebook/index.rst new file mode 100644 index 0000000..2191fda --- /dev/null +++ b/docs/source/notebook/index.rst @@ -0,0 +1,13 @@ +==================== +The IPython notebook +==================== + +.. toctree:: + :maxdepth: 2 + + notebook + cm_keyboard + nbconvert + public_server + security + diff --git a/docs/source/notebook/ipython_security.asc b/docs/source/notebook/ipython_security.asc new file mode 100644 index 0000000..9543681 --- /dev/null +++ b/docs/source/notebook/ipython_security.asc @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) + +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 +5vmLc+Ibz+eT+rM= +=XVDe +-----END PGP PUBLIC KEY BLOCK----- diff --git a/docs/source/interactive/nbconvert.rst b/docs/source/notebook/nbconvert.rst similarity index 100% rename from docs/source/interactive/nbconvert.rst rename to docs/source/notebook/nbconvert.rst diff --git a/docs/source/interactive/notebook.rst b/docs/source/notebook/notebook.rst similarity index 100% rename from docs/source/interactive/notebook.rst rename to docs/source/notebook/notebook.rst diff --git a/docs/source/interactive/public_server.rst b/docs/source/notebook/public_server.rst similarity index 98% rename from docs/source/interactive/public_server.rst rename to docs/source/notebook/public_server.rst index aae62c8..9454cd0 100644 --- a/docs/source/interactive/public_server.rst +++ b/docs/source/notebook/public_server.rst @@ -19,8 +19,8 @@ a public interface `. .. _notebook_security: -Notebook security ------------------ +Securing a notebook server +-------------------------- You can protect your notebook server with a simple single password by setting the :attr:`NotebookApp.password` configurable. You can prepare a diff --git a/docs/source/notebook/security.rst b/docs/source/notebook/security.rst new file mode 100644 index 0000000..fa68579 --- /dev/null +++ b/docs/source/notebook/security.rst @@ -0,0 +1,146 @@ +Security in IPython notebooks +============================= + +As IPython notebooks become more popular for sharing and collaboration, +the potential for malicious people to attempt to exploit the notebook +for their nefarious purposes increases. IPython 2.0 introduces a +security model to prevent execution of untrusted code without explicit +user input. + +The problem +----------- + +The whole point of IPython is arbitrary code execution. We have no +desire to limit what can be done with a notebook, which would negatively +impact its utility. + +Unlike other programs, an IPython notebook document includes output. +Unlike other documents, that output exists in a context that can execute +code (via Javascript). + +The security problem we need to solve is that no code should execute +just because a user has **opened** a notebook that **they did not +write**. Like any other program, once a user decides to execute code in +a notebook, it is considered trusted, and should be allowed to do +anything. + +Our security model +------------------ + +- Untrusted HTML is always sanitized +- Untrusted Javascript is never executed +- HTML and Javascript in Markdown cells are never trusted +- **Outputs** generated by the user are trusted +- Any other HTML or Javascript (in Markdown cells, output generated by + others) is never trusted +- The central question of trust is "Did the current user do this?" + +The details of trust +-------------------- + +IPython notebooks store a signature in metadata, which is used to answer +the question "Did the current user do this?" + +This signature is a digest of the notebooks contents plus a secret key, +known only to the user. The secret key is a user-only readable file in +the IPython profile's security directory. By default, this is:: + + ~/.ipython/profile_default/security/notebook_secret + +When a notebook is opened by a user, the server computes a signature +with the user's key, and compares it with the signature stored in the +notebook's metadata. If the signature matches, HTML and Javascript +output in the notebook will be trusted at load, otherwise it will be +untrusted. + +Any output generated during an interactive session is trusted. + +Updating trust +************** + +A notebook's trust is updated when the notebook is saved. If there are +any untrusted outputs still in the notebook, the notebook will not be +trusted, and no signature will be stored. If all untrusted outputs have +been removed (either via ``Clear Output`` or re-execution), then the +notebook will become trusted. + +While trust is updated per output, this is only for the duration of a +single session. A notebook file on disk is either trusted or not in its +entirety. + +Explicit trust +************** + +Sometimes re-executing a notebook to generate trusted output is not an +option, either because dependencies are unavailable, or it would take a +long time. Users can explicitly trust a notebook in two ways: + +- At the command-line, with:: + + ipython trust /path/to/notebook.ipynb + +- After loading the untrusted notebook, with ``File / Trust Notebook`` + +These two methods simply load the notebook, compute a new signature with +the user's key, and then store the newly signed notebook. + +Reporting security issues +------------------------- + +If you find a security vulnerability in IPython, either a failure of the +code to properly implement the model described here, or a failure of the +model itself, please report it to security@ipython.org. + +If you prefer to encrypt your security reports, +you can use :download:`this PGP public key `. + +Affected use cases +------------------ + +Some use cases that work in IPython 1.0 will become less convenient in +2.0 as a result of the security changes. We do our best to minimize +these annoyance, but security is always at odds with convenience. + +Javascript and CSS in Markdown cells +************************************ + +While never officially supported, it had become common practice to put +hidden Javascript or CSS styling in Markdown cells, so that they would +not be visible on the page. Since Markdown cells are now sanitized (by +`Google Caja `__), all Javascript +(including click event handlers, etc.) and CSS will be stripped. + +We plan to provide a mechanism for notebook themes, but in the meantime +styling the notebook can only be done via either ``custom.css`` or CSS +in HTML output. The latter only have an effect if the notebook is +trusted, because otherwise the output will be sanitized just like +Markdown. + +Collaboration +************* + +When collaborating on a notebook, people probably want to see the +outputs produced by their colleagues' most recent executions. Since each +collaborator's key will differ, this will result in each share starting +in an untrusted state. There are three basic approaches to this: + +- re-run notebooks when you get them (not always viable) +- explicitly trust notebooks via ``ipython trust`` or the notebook menu + (annoying, but easy) +- share a notebook secret, and use an IPython profile dedicated to the + collaboration while working on the project. + +Multiple profiles or machines +***************************** + +Since the notebook secret is stored in a profile directory by default, +opening a notebook with a different profile or on a different machine +will result in a different key, and thus be untrusted. The only current +way to address this is by sharing the notebook secret. This can be +facilitated by setting the configurable: + +.. sourcecode:: python + + c.NotebookApp.secret_file = "/path/to/notebook_secret" + +in each profile, and only sharing the secret once per machine.