Archived because this is mostly a silly idea and because I never finished it and don't want to give the impression that it actually allows safe execution of untrusted code.
The main legacy of this project is a PR merged into Julia that allows defining very empty modules. Try that PR with:
my_sandbox = Core.Module(:x, false, false)
@eval my_sandbox 1 # returns 1
@eval my_sandbox 1 + 1 # UndefVarError: `+` not defined in `Main.sandbox`
See the docs here.
Note that this sandbox can still be escaped with techniques like this:
@eval sandbox my_typeof(x::T) where T = T
@eval sandbox my_typeof(1).name.module # Returns `Core`
Or
@eval sandbox using Core
Sandboxes.sandboxed_eval_expr(sandbox, :(your expression here))
prevents using
and import
, but Sandboxes.jl does not stop the my_typeof
escape, and there are probably several more.
The chat that started this project can be found here
A simple sandboxing mechanism for evaluating Julia code in a restricted environment. You might want to use this if:
- You want to evaluate untrusted code and restrict what it can do
- You want to define a simpler version of Julia for teaching something or as a DSL
- Make a bare module, M
- Eval the desired interface into M
- Check an expr E to eval in M
- White or blacklist certain Expr heads and types
- Rewrite symbols that are equal to symbols in Core and
:ccall
(so the only available symbols are those that have been eval'd in)- This step unnecessary if Julia later supports more bare baremodules (https://discourse.julialang.org/t/even-more-bare-baremodule/56156/)
A valid alternative method might be to use a compiler pass like Cassette, but I don't think we need to.
This isn't implemented yet, I'm still deciding. For now, check the tests to see how to use it.
@sandboxed module M
# Your safe interfaces here
end
sandboxed_eval(M, expr)
sandboxed_include(M, file)
# Evaluate code without sandboxing, if you need to
@eval M unsandboxed_expr
It might be appropriate for us to warn if the user imports any code with anything other than using X: something_safe
.
Users will need to be cautious of eval
available on most module objects, for example.
If you need many sandboxes:
sandbox() = eval(:(@sandboxed module M ... end))
Probably want to provide a string interface for REPLs and an easy interface for disabling bits of Julia, seeing as I've done that work and it might be useful for others. Or maybe I should just provide an example and suggest they copy it to start them off, idk.
It would be useful if users could easily use the safe parts of Base
.
map
, filter
, arithmetic, etc, are probably safe :)
- eval'ing extra properties onto
Core
after a sandbox has started