The sandbox model

Computerwelt exists to be handed code you did not write. Its value is therefore not the shell but the boundary around it, and the boundary is made of absences rather than rules.

Five properties that define "correct"

1. No process spawning

Every command is a managed C# implementation. There is no PATH, no fork and no exec. A "builtin" that shelled out would be a bug, not a shortcut, because it would hand the script the host's authority in one step.

A name the session does not implement is simply not found, and exits 127.

2. No ambient filesystem access

All file I/O goes through IFileSystem. Nothing in the interpreter calls System.IO.File or Directory except the backend a host explicitly chose. The default backend is an empty in-memory tree, so a session built with no filesystem configured can read nothing at all.

3. No ambient network access

Nothing in the sandbox performs an outbound request. The shell ships no networking commands, and a host that wants HTTP has to configure it deliberately.

4. Deterministic, enforced limits

Command count, loop iterations, function depth, output size, filesystem size, directory depth, parser fuel and wall-clock time are all charged during evaluation. They are enforced, not advisory, and never silently: a cap that is reached raises, because a traversal that quietly stopped part-way would report a subset as though it were the whole. See Limits.

5. Multi-tenant isolation

Two Bash instances share no mutable state. A builtin registered with both is shared, which is why one must be stateless and thread-safe, but everything an invocation can see arrives in its context rather than being held on the instance.

POSIX paths on every host

Virtual paths are POSIX even when the host is Windows. That is why the library has its own VPath type and never uses System.IO.Path for a virtual path: Path.Combine("/a", "C:\\b") and its relatives are host-dependent, and a host-dependent path join in a sandbox is a hole straight through it.

A consequence worth knowing: a script behaves identically on Linux, macOS and Windows, and a test that passes on one passes on the others.

Where the boundary actually sits

A host command is inside the sandbox, not beside it

Everything the host registers runs under the same limits, against the same virtual filesystem, with no route out that the sandbox did not already have. A host command is a way to give a script more vocabulary; it is not a way to give it more authority, unless the code you register reaches for something itself.

So the real security question is not "can a script escape?" but "what did I register?". A builtin that opens a socket, or a Python host function that reads the host disk, is an authority the host granted deliberately. The library will not stop you; it just never does it on your behalf.

The other half of the same rule: errors do not leak. A host exception reaching a sandboxed program would be the sandbox leaking, so a failure crossing into Python is translated at the boundary into a Python exception the program can catch, rather than an exception it cannot name.

Depth is capped twice, on purpose

Path depth is capped both where paths are created (the filesystem's own limit) and where they are walked (the execution limit). The first is the containment. The second is the backstop for a host-supplied filesystem this sandbox did not build, and therefore cannot assume is shallow.

© 2026 Curiosity. All rights reserved.