Dune (dune v0.2.1) View Source
A sandbox for Elixir to safely evaluate untrusted code from user input.
Features
- only authorized modules and functions can be executed (see
Dune.Allowlist.Default
) - no access to environment variables, file system, network...
- code executed in an isolated process
- execution within configurable limits: timeout, maximum reductions and memory (inspired by Luerl)
- captured standard output
- atoms, without atom leaks: parsing and runtime do not leak atoms (i.e. does not keep filling the atom table until the VM crashes)
- modules, without actual module creation: Dune does not let users define any
actual module (would leak memory and modify the state of the VM globally), but
defmodule
simulates the basic behavior of a module, including private and recursive functions
The list of modules and functions authorized by default is defined by the
Dune.Allowlist.Default
module, but this list can be extended and customized
(at your own risk!) using Dune.Allowlist
.
If you need to keep the state between evaluations, you might consider
Dune.Session
.
Link to this section Summary
Link to this section Functions
Specs
eval_quoted(Macro.t(), Keyword.t()) :: Dune.Success.t() | Dune.Failure.t()
Evalates the quoted ast in the sandbox.
Available options are detailed in Dune.Parser.Opts
(for parsing-time restrictions)
and in Dune.Eval.Opts
(for runtime restrictions).
Returns a Dune.Success
struct if the execution went successfully,
a Dune.Failure
else.
Examples
iex> Dune.eval_quoted(quote do: [1, 2] ++ [3, 4])
%Dune.Success{inspected: "[1, 2, 3, 4]", stdio: "", value: [1, 2, 3, 4]}
iex> Dune.eval_quoted(quote do: System.get_env())
%Dune.Failure{message: "** (DuneRestrictedError) function System.get_env/0 is restricted", type: :restricted}
iex> Dune.eval_quoted(quote do: Process.sleep(500))
%Dune.Failure{message: "Execution timeout - 50ms", type: :timeout}
Specs
eval_string(String.t(), Keyword.t()) :: Dune.Success.t() | Dune.Failure.t()
Evaluates the string in the sandbox.
Available options are detailed in Dune.Parser.Opts
(for parsing-time restrictions)
and in Dune.Eval.Opts
(for runtime restrictions).
Returns a Dune.Success
struct if the execution went successfully,
a Dune.Failure
else.
Examples
iex> Dune.eval_string("IO.puts('Hello world!')")
%Dune.Success{inspected: ":ok", stdio: "Hello world!\n", value: :ok}
iex> Dune.eval_string("File.cwd!()")
%Dune.Failure{message: "** (DuneRestrictedError) function File.cwd!/0 is restricted", type: :restricted}
iex> Dune.eval_string("List.duplicate(:spam, 100_000)")
%Dune.Failure{message: "Execution stopped - memory limit exceeded", stdio: "", type: :memory}
iex> Dune.eval_string("Foo.bar()")
%Dune.Failure{message: "** (UndefinedFunctionError) function Foo.bar/0 is undefined (module Foo is not available)", type: :exception}
iex> Dune.eval_string("][")
%Dune.Failure{message: "unexpected token: ]", type: :parsing}
Atoms used during parsing and execution might be transformed to prevent atom leaks:
iex> Dune.eval_string("some_variable = IO.inspect(:some_atom)")
%Dune.Success{inspected: ":some_atom", stdio: ":some_atom\n", value: :a__Dune_atom_2__}
The value
field shows the actual value, but inspected
and stdio
are safe to display to the user.