The task is to execute some code that comes from a (possibly) untrusted source.
-- make environment local env = {}
-- run code under environment local function run(code)
local fun, message = loadstring(code)
if not fun then return nil, message end
setfenv(fun, env)
return pcall(fun)
end
First the code is compiled into a function, then we set the environment for the function, and finally that function is called using pcall
, so that we can catch errors. You could of course also use loadfile
here.
Note that if you want to load code and repeatedly execute it, you should store the compiled function and pcall
it whenever needed.
The code may come from anywhere. This is the classic 'sand-boxing' problem, (see Sandboxing.) The key to making such code as safe as possible is to restrict the environment of the function. Without the
setfenv
call, the function will run in the global environment and can of course call any Lua function, potentially causing a lot of damage. So the sand-boxing approach involves starting with an empty environment and only adding those functions which you want the user to use, excluding those which are 'unsafe'.
As for including your own modules in the sand boxed environment, note that module('mymod',package.seeall)
is a definite security risk. This call works by creating a new environment in the table mymod
, and then setting
__index
to be _G
- so anybody can access global functions through your module, as simply as mymod._G
! So resist the temptation to use package.seeall
.
For Lua 5.2, an equivalent function would be:
function run (code)
local fun, message = load(code,"tmp","t",env)
if not fun then return nil, message end
return pcall(fun)
end