Skip to content

Commit 73e1375

Browse files
brichetminrk
andauthored
Revert #1915 for security reason (#1947)
* Revert "Set CSP frame-ancestors 'self' for nbgrader handlers (#1915)" This reverts commit ba1e70b. * Update demos to set frame-ancestor 'self' * Update documentation on installation with jupyterhub>=4.1 * linting * Fix documentation titles * typo * Include PR suggestions Co-authored-by: Min RK <[email protected]> --------- Co-authored-by: Min RK <[email protected]>
1 parent 895aa7d commit 73e1375

File tree

7 files changed

+85
-4
lines changed

7 files changed

+85
-4
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
c = get_config()
2+
3+
c.ServerApp.tornado_settings = {}
4+
c.ServerApp.tornado_settings["headers"] = {
5+
"Content-Security-Policy": "frame-ancestors 'self'"
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
c = get_config()
2+
3+
c.ServerApp.tornado_settings = {}
4+
c.ServerApp.tornado_settings["headers"] = {
5+
"Content-Security-Policy": "frame-ancestors 'self'"
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
c = get_config()
2+
3+
c.ServerApp.tornado_settings = {}
4+
c.ServerApp.tornado_settings["headers"] = {
5+
"Content-Security-Policy": "frame-ancestors 'self'"
6+
}

demos/utils.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ setup_jupyterhub () {
5858

5959
# Copy config file.
6060
cp jupyterhub_config.py "${jupyterhub_root}/jupyterhub_config.py"
61+
cp jupyter_server_config.py /usr/local/etc/jupyter/jupyter_server_config.py
6162
}
6263

6364
enable_create_assignment () {
40.9 KB
Loading

nbgrader/docs/source/configuration/jupyterhub_config.rst

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ Using nbgrader with JupyterHub
2020
much required reading if you want to integrate the formgrader with
2121
JupyterHub.
2222

23+
.. warning::
24+
25+
For security reasons, ``iframe`` are not allowed with JupyterHub from version 4.1. The
26+
documentation about this security change is at
27+
`mitigating-same-origin-deployments <https://jupyterhub.readthedocs.io/en/stable/explanation/websecurity.html#mitigating-same-origin-deployments>`_.
28+
29+
In the current version of nbgrader, the ``formgrader`` UI is embedded in an ``iframe``, to
30+
be available in a new tab of Jupyterlab or Notebook. Therefore, the ``formgrader`` UI can't
31+
be loaded when using ``jupyterhub>=4.1``, and shows a blank panel instead.
32+
33+
There are several ways to use the ``formgrader`` with ``jupyterhub>=4.1``, see details
34+
at :ref:`jupyterhub-4.1`.
35+
36+
2337
For instructors running a class with JupyterHub, nbgrader offers several tools
2438
that optimize and enrich the instructors' and students' experience of sharing
2539
the same system. By integrating with JupyterHub, nbgrader streamlines the
@@ -331,3 +345,55 @@ API
331345
.. automethod:: add_student_to_course
332346

333347
.. automethod:: remove_student_from_course
348+
349+
350+
.. _jupyterhub-4.1:
351+
352+
Formgrader with ``jupyterhub>=4.1``
353+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
354+
355+
As explained above in the warning, ``jupyterhub>=4.1`` does not allow iframe for security
356+
reasons, which lead to blank panel instead of the ``formgrader`` UI.
357+
358+
Below are different ways to use the ``formgrader`` UI with ``jupyterhub>=4.1``.
359+
360+
Opening the ``formgrader`` UI in a new browser tab
361+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
362+
363+
Web browsers are able to open iframes in a new browser tab, which allows using the
364+
``formgrader`` without any additional setting on the jupyterhub server.
365+
For example with Firefox, right clicking on the iframe shows a context menu to open the
366+
contents in a new browser tab.
367+
368+
.. image:: images/jupyterhub_4.1_iframe.png
369+
370+
Although this solution isn't the most practical, it does allow to use ```formgrader``
371+
without having to update the configuration and without adding vulnerabilities to the application.
372+
373+
Enabling JupyterHub subdomains
374+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
375+
376+
Enabling per-user and per-service subdomains with ``JupyterHub.enable_subdomains = True``
377+
allows to securely use iframes with JupyterHub.
378+
With subdomains enabled, `frame-ancestors 'self'` allows embedding the iframe only on pages
379+
served by the user's own server.
380+
381+
In this case, the ``"frame-ancestor 'self'"`` can be restored in the application:
382+
383+
.. code:: python
384+
385+
c.ServerApp.tornado_settings = {}
386+
c.ServerApp.tornado_settings["headers"] = {
387+
"Content-Security-Policy": "frame-ancestors 'self'"
388+
}
389+
390+
in e.g. ``/usr/local/etc/jupyter/jupyter_server_config.py``.
391+
392+
Trusting users (less secure)
393+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
394+
395+
If you trust users and are aware of the security vulnerability, it is also possible to
396+
enable the iframe with the same configuration as above, without subdomains.
397+
398+
This is the solution used in the JupyterHub docker
399+
`demo <https://github.com/jupyter/nbgrader/tree/main/demos>`_.

nbgrader/server_extensions/formgrader/base.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@ def api(self):
6060
api.log_level = level
6161
return api
6262

63-
def initialize(self):
64-
super().initialize()
65-
self.set_header("Content-Security-Policy", "frame-ancestors 'self'")
66-
6763
def render(self, name, **ns):
6864
template = self.settings['nbgrader_jinja2_env'].get_template(name)
6965
return template.render(**ns)

0 commit comments

Comments
 (0)