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.
Read next
- The virtual filesystem — the one route to data.
- Limits — the budgets and their defaults.
- Extending the shell — adding vocabulary without adding authority.