Run notebook with a sandboxed kernel?

Hi, I’m working on a solution that allows grading notebooks. One potential issue is that a student might put malicious code in their notebook. I don’t know how much this is a problem in practice, but at least theoretically it is a concern.

Is there a way to run a notebook such that the code inside can only access certain files, like in a chroot or a container?

I know I can just run a new Jupyter(Lab) instance as a restricted user. But can I somehow stay logged in as my user and run only one tab in a sandbox? Maybe by running a special kernel, or running the kernel or the user server in a different context? I am aware that there are solutions to run the whole notebook in a container, but I’m looking for something that allows you to safely run it interactively (for manual grading and marking).


Unfortunately, there is no truly “safe” interactive computing against untrusted content, and very few “clever” techniques (scrubbing, etc) work.

You’d pretty much want to use as many layers of defense-in-depth as possible, both on the kernel side (run in a container in a VM) and browser-side (e.g. run in a container in a vm, generate a PDF/PNG of the output).

For certain use cases, it would be possible to remove the server aspect and use browser-only tools such as pyodide, as wrapped by JupyterLite. These could be run on an iframe in a separate domain which would be as many layers as the browser can provide, but zero-click image/style XSS hacks are real, and the jupyter infrastructure can’t help you if you’re actually going to run them.

One direction that may become interesting is enarx which would layer in the additional benefits/compromises of WebAssembly, which is at least partially sandboxed… but this still can’t save you from browser-side XSS, etc.


Hi @jdmansour,

You might be interested by travo which we developed as a thin end-to-end assignment management tool, akin to GitHub ClassRoom, and using nbgrader for authoring/grading jupyter notebooks. It requires no infrastructure beyond access to some GitLab forge. And a way for students to run Jupyter, e.g. a JupyterHub.

Notebooks are graded by continuous integration on GitLab; hence containerized. This does not totally prevent students from doing silly things like trying to bitcoin with very limited computer resources available, or doing various network connections. But this would leave a big trace (execution log, exact state of their code when grading occurs). So far we have noticed no abuse. If needed, it should be possible to configure continuous integration to run without network.


travo looks lovely! A software forge (if not GitLab) is where I often recommend folks looking, if they are able, mapping the well-established, sclalable, programmable identity, persistence, and workflow building blocks to their end user domain.

Here’s a little write-up I’ve done about using the “push to deploy” feature of many forges (e.g. Git…b Pages). In short: host a Jupyter-based UI that uses the underlying API of the forge to read, but crucially write, workflow content.

Of course, this would be a mountain of work, even for the first instance that still looked like JupyterLab, but the longer-con goal is to support things that aren’t even related to code, but reuse the Jupyter principals.

1 Like

Hmm, thanks for the pointer, and the thought provoking idea!

It indeed would be a mountain of work if one aims at replicating in JupyterLab
UI to access all of the forge’s features. But hopefully in many uses cases,
what one just needs is a few dashboards that give a high
level perspective on the forge customized to the end user domain and
structure the workflow, but delegate as much of the specifics as possible
to the existing forge’s UI. “thin end-domain oriented layer on top of existing
generic infrastructure”.

delegate as much of the specifics as possible to the existing forge’s UI

Right, initially: but most forge UIs are still terrifying for many non-software folk! I think once such an implementation can get to single/zero-click “search,” “make PR,” “comment on PR,” “submit change,” for a given forge, it would be pretty workable, potentially with a very small number of clicks to do those things, given a focused task.

mountain of work

I guess I minorly overstate the case… I’ve done a lot of work (alas, not open source) around this for a single use case, on a single forge (happened to be gitlab).

customized to the end user domain

The challenge laid out in the linked proposal is indeed enabling domain-specific UI, delivered with radically simplifying access to forge-level collaboration. If it mentions a “commit,” it’s probably dead in the water.

Scaling down is hard, of course: I really think there’s a place for very small forges like fossil. The JS served from a GitLab page for an empty repo is larger than the entire fossil binary. But it (not entirely unsurprisingly) doesn’t have CI… but perhaps that can be solved simply, as well… which puts us back in the question at the top of this thread, which I’ve so crudely stolen.