package workers // setupSandbox initializes the sandbox environment creation function func (w *worker) setupSandbox() error { // This is the Lua script that creates our sandbox function setupScript := ` -- Create a function to run code in a sandbox environment function __create_sandbox() -- Create new environment table local env = {} -- Add standard library modules (can be restricted as needed) env.string = string env.table = table env.math = math env.os = { time = os.time, date = os.date, difftime = os.difftime, clock = os.clock } env.tonumber = tonumber env.tostring = tostring env.type = type env.pairs = pairs env.ipairs = ipairs env.next = next env.select = select env.unpack = unpack env.pcall = pcall env.xpcall = xpcall env.error = error env.assert = assert -- Allow access to package.loaded for modules env.require = function(name) return package.loaded[name] end -- Create metatable to restrict access to _G local mt = { __index = function(t, k) -- First check in env table local v = rawget(env, k) if v ~= nil then return v end -- If not found, check for registered modules/functions local moduleValue = _G[k] if type(moduleValue) == "table" or type(moduleValue) == "function" then return moduleValue end return nil end, __newindex = function(t, k, v) rawset(env, k, v) end } setmetatable(env, mt) return env end -- Create function to execute code with a sandbox function __run_sandboxed(f, ctx) local env = __create_sandbox() -- Add context to the environment if provided if ctx then env.ctx = ctx end -- Set the environment and run the function setfenv(f, env) return f() end ` return w.state.DoString(setupScript) } // executeJobSandboxed runs a script in a sandbox environment func (w *worker) executeJobSandboxed(j job) JobResult { // No need to reset the state for each execution, since we're using a sandbox // Re-run init function to register functions and modules if needed if w.pool.stateInit != nil { if err := w.pool.stateInit(w.state); err != nil { return JobResult{nil, err} } } // Set up context if provided if j.Context != nil { // Push context table w.state.NewTable() // Add values to context table for key, value := range j.Context.Values { // Push key w.state.PushString(key) // Push value if err := w.state.PushValue(value); err != nil { return JobResult{nil, err} } // Set table[key] = value w.state.SetTable(-3) } } else { // Push nil if no context w.state.PushNil() } // Load bytecode if err := w.state.LoadBytecode(j.Bytecode, "script"); err != nil { w.state.Pop(1) // Pop context return JobResult{nil, err} } // Get the sandbox runner function w.state.GetGlobal("__run_sandboxed") // Push loaded function and context as arguments w.state.PushCopy(-2) // Copy the loaded function w.state.PushCopy(-4) // Copy the context table or nil // Remove the original function and context w.state.Remove(-5) // Remove original context w.state.Remove(-4) // Remove original function // Call the sandbox runner with 2 args (function and context), expecting 1 result if err := w.state.Call(2, 1); err != nil { return JobResult{nil, err} } // Get result value, err := w.state.ToValue(-1) w.state.Pop(1) // Pop result return JobResult{value, err} }