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

Functions

Evalates the quoted ast in the sandbox.

Evaluates the string in the sandbox.

Link to this section Functions

Link to this function

eval_quoted(ast, opts \\ [])

View Source

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}
Link to this function

eval_string(string, opts \\ [])

View Source

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.