I wanted to create a way to “safely” evaluate a string containing Elixir code. The code in the string should not be allowed to use any functions or modules (not even those from the Kernel e.g. defmodule/2).
Have I succeeded, or are there still ways to create a string that will allow the function to succeed while violating my criteria above?
def safe_eval(code) when is_binary(code) do
quoted_form = Code.string_to_quoted!(code, existing_atoms_only: true)
Macro.postwalk(quoted_form, fn node ->
if is_tuple(node) and (Kernel.elem(node, 0) in [:__aliases__]) do
raise "Cannot use aliases or references to other modules"
end
end)
{evaluated, _bindings} = Code.eval_string(code, [], %Macro.Env{})
{"ok", evaluated}
end