yuin / gopher-lua

GopherLua: VM and compiler for Lua in Go
MIT License
6.27k stars 652 forks source link

Whitelisting when sandboxing a VM #348

Open ragnarlonn opened 3 years ago

ragnarlonn commented 3 years ago

Hi, and thanks for creating this great Golang Lua VM!

I've been trying to do some sandboxing and failed to find good support for it in gopher-lua. The methods suggested by @yuin and others (in e.g. issue #11) are all about blacklisting functionality you want to disable, rather than whitelisting things you want to enable. Whitelisting is much better, but as of now, it seems you can only whitelist entire libraries (by creating the LState with the SkipOpenLibs option and then calling OpenXXX() for the libs you want to enable).

I find that I want to enable some functions in e.g. "os", but not all of them. It would be really neat if it was possible to select exactly what functionality you want from a library, when loading it. I may have found a way to do this without breaking the current API, but I'm new to this whole code base so sorry if I'm suggesting something completely stupid ;)

What if e.g. OpenBase() was defined as OpenBase(L *LState, enableFuncs ...string) and then OpenBase() does something like:

Below definition of OpenBase() is not correct. Look at next comment instead

func OpenBase(L *LState, enableFuncs ...string) int {
   ...
   baseFuncsToEnable := baseFuncs
   if len(enableFuncs) > 0 {
      baseFuncsToEnable := map[string]LGFunction{}
      for k, v := range baseFuncsToEnable {
         baseFuncsToEnable[k] = v
      }
   }
   basemod := L.RegisterModule("_G", baseFuncsToEnable)
   ...
}

Then old code should work, and it would be possible to specify a list of things you want added, when calling OpenBase():

L := lua.NewState(lua.Options{SkipOpenLibs: true})
defer L.Close()
enableBaseFunctions := []string{"assert","error","print","tonumber","tostring"}
OpenBase(L, enableBaseFunctions...)
ragnarlonn commented 3 years ago

Uh, that code did not come out right. I meant something like this:

func OpenBase(L *LState, enableFuncs ...string) int {
   ...
   baseFuncsToEnable := baseFuncs
   if len(enableFuncs) > 0 {
      baseFuncsToEnable := map[string]LGFunction{}
      for _, funcName := range enableFuncs {
         baseFuncsToEnable[funcName] = baseFuncs[funcName]
      }
   }
   basemod := L.RegisterModule("_G", baseFuncsToEnable)
   ...
}
ragnarlonn commented 3 years ago

Hmm, I just saw this is pretty much a duplicate of #255