Treat access to a Jupyter server as access to run arbitrary code, because that is what it is. Keep token authentication on, do not expose the port to the internet, put an access layer in front, and give each person only the credentials their work needs.
Why this deserves attention
Jupyter's documentation says token authentication is enabled by default because access to the server means access to running arbitrary code. If a server is reachable and unauthenticated, an outsider can open a terminal inside your network, with whatever data, GPUs and keys that machine can reach.
ML teams often run these servers on powerful, well connected machines. That makes them attractive and easy to forget.
What Jupyter provides by default
- Token authentication is on. The token is printed at startup, and jupyter server list shows running servers and their tokens.
- Setting a password turns token authentication off by default. The docs strongly discourage disabling both unless another layer handles access control.
- ZMQ sockets used by kernels are unencrypted by default, so a local process that can reach those ports can read messages, including output. Encryption with CurveZMQ is available, though the setting defaults to disabled and needs a pyzmq build with libsodium.
Hardening checklist
- Keep authentication on. Do not set the token to an empty string.
- Bind to localhost or a private interface. Reach it through a tunnel or an authenticated proxy, not a public IP.
- Put identity in front. Use your company login at a proxy rather than a shared token passed around in chat.
- Use TLS on any link that leaves the machine.
- One user, one environment. Avoid a single shared account where everyone's files and credentials mix.
- No long lived cloud keys on the box. Prefer short lived credentials scoped to the job.
- Limit outbound network access from the notebook host where you can.
- Patch regularly. Jupyter, its extensions and the Python packages are dependencies like any other.
- Log and review. Know who started which server and when.
Common mistakes
| Mistake | Why it hurts |
|---|---|
| Starting a server on all interfaces for convenience | Anyone on the network can try it |
| Pasting the token URL into a shared channel | The token is the password |
| Disabling auth in a cloud VM | Public IPs get scanned constantly |
| Leaving old servers running | Forgotten hosts do not get patched |
| Storing keys in notebook cells | They end up in version control |
Notebooks and extensions are software too
Every extension you install adds code to the server. Track them. Remove the ones nobody uses. Our post on opening notebooks from the internet covers the user side of the same problem.
Where Safeguard fits
Safeguard helps with the dependency side. It can inventory the packages on your ML hosts with SBOM and dependency scanning, show which vulnerabilities your code reaches, and apply policy gates. Start with a free scan at gold.safeguard.sh/scan.
Quick check
Is a password enough instead of a token?
A password can work, but the documentation notes that setting one turns token authentication off by default. Make sure something strong remains in front of the server.
Is kernel traffic encrypted by default?
According to the docs, no. The transport encryption setting defaults to disabled, so limit who can reach those ports.
Sources
Last reviewed: 19 October 2026.