mirror of
https://github.com/jupyter/notebook.git
synced 2025-03-01 12:56:54 +08:00
add notebook security doc
This commit is contained in:
parent
b294bf7059
commit
bb06f92705
148
docs/source/notebook/security.rst
Normal file
148
docs/source/notebook/security.rst
Normal file
@ -0,0 +1,148 @@
|
||||
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 this PGP public key:
|
||||
|
||||
.. literalinclude:: ipython_security.asc
|
||||
|
||||
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 <https://developers.google.com/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.
|
Loading…
Reference in New Issue
Block a user