CVE-2025-23205
Description
nbgrader is a system for assigning and grading notebooks. Enabling frame-ancestors: 'self' grants any JupyterHub user the ability to extract formgrader content by sending malicious links to users with access to formgrader, at least when using the default JupyterHub configuration of enable_subdomains = False. #1915 disables a protection which would allow user Alice to craft a page embedding formgrader in an IFrame. If Bob visits that page, his credentials will be sent and the formgrader page loaded. Because Alice's page is on the same Origin as the formgrader iframe, Javasript on Alice's page has _full access_ to the contents of the page served by formgrader using Bob's credentials. This issue has been addressed in release 0.9.5 and all users are advised to upgrade. Users unable to upgrade may disable frame-ancestors: self, or enable per-user and per-service subdomains with JupyterHub.enable_subdomains = True (then even if embedding in an IFrame is allowed, the host page does not have access to the contents of the frame).
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
nbgraderPyPI | >= 0.9.4, < 0.9.5 | 0.9.5 |
Patches
173e137511ac1Revert #1915 for security reason (#1947)
7 files changed · +85 −4
demos/demo_multiple_classes/jupyter_server_config.py+6 −0 added@@ -0,0 +1,6 @@ +c = get_config() + +c.ServerApp.tornado_settings = {} +c.ServerApp.tornado_settings["headers"] = { + "Content-Security-Policy": "frame-ancestors 'self'" +}
demos/demo_one_class_multiple_graders/jupyter_server_config.py+6 −0 added@@ -0,0 +1,6 @@ +c = get_config() + +c.ServerApp.tornado_settings = {} +c.ServerApp.tornado_settings["headers"] = { + "Content-Security-Policy": "frame-ancestors 'self'" +}
demos/demo_one_class_one_grader/jupyter_server_config.py+6 −0 added@@ -0,0 +1,6 @@ +c = get_config() + +c.ServerApp.tornado_settings = {} +c.ServerApp.tornado_settings["headers"] = { + "Content-Security-Policy": "frame-ancestors 'self'" +}
demos/utils.sh+1 −0 modified@@ -58,6 +58,7 @@ setup_jupyterhub () { # Copy config file. cp jupyterhub_config.py "${jupyterhub_root}/jupyterhub_config.py" + cp jupyter_server_config.py /usr/local/etc/jupyter/jupyter_server_config.py } enable_create_assignment () {
nbgrader/docs/source/configuration/images/jupyterhub_4.1_iframe.png+0 −0 addednbgrader/docs/source/configuration/jupyterhub_config.rst+66 −0 modified@@ -20,6 +20,20 @@ Using nbgrader with JupyterHub much required reading if you want to integrate the formgrader with JupyterHub. +.. warning:: + + For security reasons, ``iframe`` are not allowed with JupyterHub from version 4.1. The + documentation about this security change is at + `mitigating-same-origin-deployments <https://jupyterhub.readthedocs.io/en/stable/explanation/websecurity.html#mitigating-same-origin-deployments>`_. + + In the current version of nbgrader, the ``formgrader`` UI is embedded in an ``iframe``, to + be available in a new tab of Jupyterlab or Notebook. Therefore, the ``formgrader`` UI can't + be loaded when using ``jupyterhub>=4.1``, and shows a blank panel instead. + + There are several ways to use the ``formgrader`` with ``jupyterhub>=4.1``, see details + at :ref:`jupyterhub-4.1`. + + For instructors running a class with JupyterHub, nbgrader offers several tools that optimize and enrich the instructors' and students' experience of sharing the same system. By integrating with JupyterHub, nbgrader streamlines the @@ -331,3 +345,55 @@ API .. automethod:: add_student_to_course .. automethod:: remove_student_from_course + + +.. _jupyterhub-4.1: + +Formgrader with ``jupyterhub>=4.1`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As explained above in the warning, ``jupyterhub>=4.1`` does not allow iframe for security +reasons, which lead to blank panel instead of the ``formgrader`` UI. + +Below are different ways to use the ``formgrader`` UI with ``jupyterhub>=4.1``. + +Opening the ``formgrader`` UI in a new browser tab +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Web browsers are able to open iframes in a new browser tab, which allows using the +``formgrader`` without any additional setting on the jupyterhub server. +For example with Firefox, right clicking on the iframe shows a context menu to open the +contents in a new browser tab. + +.. image:: images/jupyterhub_4.1_iframe.png + +Although this solution isn't the most practical, it does allow to use ```formgrader`` +without having to update the configuration and without adding vulnerabilities to the application. + +Enabling JupyterHub subdomains +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Enabling per-user and per-service subdomains with ``JupyterHub.enable_subdomains = True`` +allows to securely use iframes with JupyterHub. +With subdomains enabled, `frame-ancestors 'self'` allows embedding the iframe only on pages +served by the user's own server. + +In this case, the ``"frame-ancestor 'self'"`` can be restored in the application: + +.. code:: python + + c.ServerApp.tornado_settings = {} + c.ServerApp.tornado_settings["headers"] = { + "Content-Security-Policy": "frame-ancestors 'self'" + } + +in e.g. ``/usr/local/etc/jupyter/jupyter_server_config.py``. + +Trusting users (less secure) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you trust users and are aware of the security vulnerability, it is also possible to +enable the iframe with the same configuration as above, without subdomains. + +This is the solution used in the JupyterHub docker +`demo <https://github.com/jupyter/nbgrader/tree/main/demos>`_.
nbgrader/server_extensions/formgrader/base.py+0 −4 modified@@ -60,10 +60,6 @@ def api(self): api.log_level = level return api - def initialize(self): - super().initialize() - self.set_header("Content-Security-Policy", "frame-ancestors 'self'") - def render(self, name, **ns): template = self.settings['nbgrader_jinja2_env'].get_template(name) return template.render(**ns)
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-fcr8-4r9f-r66mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-23205ghsaADVISORY
- github.com/jupyter/nbgrader/commit/73e137511ac1dc02e95790d4fd6d4d88dab42325nvdWEB
- github.com/jupyter/nbgrader/pull/1915nvdWEB
- github.com/jupyter/nbgrader/security/advisories/GHSA-fcr8-4r9f-r66mnvdWEB
- jupyterhub.readthedocs.io/en/stable/explanation/websecurity.htmlghsaWEB
- jupyterhub.readthedocs.io/en/stable/explanation/websecurity.htmlnvd
News mentions
0No linked articles in our index yet.