Managing Jupyter Notebook Trust for HTML and JavaScript Outputs
Learn how Jupyter's trust model uses cryptographic signatures and server secrets to control HTML/JS rendering, and how to properly trust notebooks using the CLI.
13 Sept 2026, 20:20 UTC

When opening a Jupyter notebook in JupyterLab or the Classic Notebook, you may find that interactive charts, HTML tables, or JavaScript-based visualizations are replaced by a warning badge or sanitized placeholders. This occurs because the notebook is "untrusted." This is not a software bug, but a security feature designed to prevent the automatic execution of potentially malicious code in your browser.
The Core Takeaway
Trust in Jupyter is a per-notebook cryptographic signature tied to a specific server's secret key. It determines whether rich output MIME types—specifically HTML and JavaScript—are rendered or sanitized. Trust is not a user permission; it is a content-integrity check. If a notebook is moved to a different server or its source code is modified, the signature becomes invalid and the notebook reverts to an untrusted state.
How the Trust Mechanism Works
Jupyter uses a signature-based system to track trust. When a notebook is saved by a user with write access to the server's content directory, or explicitly trusted via the CLI, the server generates a hash of the notebook's contents combined with a server-specific secret. This hash is stored in the notebook's JSON metadata under a signatures field.
Upon loading a notebook, the server re-computes the hash using its current secret. If the computed hash matches the stored signature, the notebook is marked as trusted. If they mismatch—or if the signature is missing—the notebook is treated as untrusted, and the frontend sanitizes all HTML and JavaScript outputs to prevent Cross-Site Scripting (XSS) attacks.
- Scope: Trust is a property of the entire notebook, not individual cells.
- Dependency: Trust is bound to the server secret; it does not transfer across different Jupyter deployments.
- Invalidation: Any change to the notebook's source code invalidates the signature.
Worked Example: Trusting a Notebook with HTML Output
Consider a scenario where you use IPython.display.HTML to render a custom data table. By default, this output may be blocked if the notebook is untrusted.
1. Create the HTML Output
In a notebook cell, execute the following code to generate HTML content:
from IPython.display import HTML
HTML('<div style="color: red; font-weight: bold;">Security Check: HTML Rendered</div>')2. Identify the Untrusted State
Open the notebook in JupyterLab. Look for the "Untrusted" badge in the top-right corner. You will notice the HTML output is either missing or replaced by a sanitized version because the browser is blocking the execution of the embedded HTML/JS.
3. Explicitly Trust the Notebook
To enable the output, you must sign the notebook using the Jupyter CLI on the host machine running the server.
jupyter trust /path/to/your_notebook.ipynb- Where to run: The terminal/command line of the machine hosting the Jupyter server.
- Required permissions: Write access to the
.ipynbfile. - Placeholder: Replace
/path/to/your_notebook.ipynbwith the absolute or relative path to your file. - Expected result: Refresh the browser page. The "Untrusted" badge should disappear, and the red bold text should render.
- Risk: Only run this command on notebooks you have authored or audited. Trusting a notebook from an unknown source allows any embedded JavaScript to run in your browser session, potentially exfiltrating cookies or session tokens.
Verifying Trust Across Different Servers
Because trust depends on a server secret, it is not portable. You can verify this behavior with the following test:
- Create and trust a notebook on Server A. Confirm the HTML renders.
- Copy the
.ipynbfile to Server B (which has a different secret). - Open the notebook on Server B. The notebook will appear as "Untrusted" despite being trusted on Server A.
- Run
jupyter truston Server B to re-establish trust.
Limitations and Common Pitfalls
The "Safe Code" Fallacy
A common misconception is that trusting a notebook makes the code safe. Trust only controls the output rendering. Malicious JavaScript embedded in an output cell can still perform actions on behalf of the user within the browser context, regardless of whether the Python code itself is benign.
Global Configuration Risks
Some administrators set c.NotebookApp.trust_notebook = False in the configuration file to prevent automatic trusting on save. While this increases security, it can break automated workflows (like report generation) where users expect rich outputs to be visible immediately upon opening a saved file.
Granularity Limits
There is no mechanism to trust a single cell while keeping the rest of the notebook untrusted. The signature is all-or-nothing for the entire file.
Practical Verification Checklist
- Check Status: Open a notebook and look for the "Untrusted" badge in the UI.
- List Trusted: Run
jupyter trust --listto see which notebooks are currently signed for the active server secret. - Test Modification: Edit a cell in a trusted notebook and reload; verify that the notebook reverts to "Untrusted" until re-signed.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.