lua: allow os time functions in sandbox

This commit is contained in:
Meo597
2026-10-15 04:33:35 +08:00
parent c2a9b074f4
commit ef4f4888df
2 changed files with 24 additions and 5 deletions
+11
View File
@@ -107,6 +107,7 @@ func newSandboxedState() *glua.LState {
{glua.TabLibName, glua.OpenTable}, {glua.TabLibName, glua.OpenTable},
{glua.StringLibName, glua.OpenString}, {glua.StringLibName, glua.OpenString},
{glua.MathLibName, glua.OpenMath}, {glua.MathLibName, glua.OpenMath},
{glua.OsLibName, glua.OpenOs},
} { } {
L.Push(L.NewFunction(lib.open)) L.Push(L.NewFunction(lib.open))
L.Push(glua.LString(lib.name)) L.Push(glua.LString(lib.name))
@@ -194,6 +195,16 @@ func newSandboxedState() *glua.LState {
// Prevent seed output from compromising cryptographic security. // Prevent seed output from compromising cryptographic security.
L.GetGlobal(glua.MathLibName).(*glua.LTable).RawSetString("randomseed", glua.LNil) L.GetGlobal(glua.MathLibName).(*glua.LTable).RawSetString("randomseed", glua.LNil)
// Keep only time functions, including when os is accessed through require.
osLib := L.GetGlobal(glua.OsLibName).(*glua.LTable)
osLib.ForEach(func(key, _ glua.LValue) {
switch key {
case glua.LString("clock"), glua.LString("date"), glua.LString("difftime"), glua.LString("time"):
default:
osLib.RawSet(key, glua.LNil)
}
})
// Prevent module injection through the global package table. // Prevent module injection through the global package table.
module := L.GetGlobal(glua.LoadLibName).(*glua.LTable) module := L.GetGlobal(glua.LoadLibName).(*glua.LTable)
preload := module.RawGetString("preload").(*glua.LTable) preload := module.RawGetString("preload").(*glua.LTable)
+13 -5
View File
@@ -553,17 +553,25 @@ func TestProgramSandbox(t *testing.T) {
local function check() local function check()
assert(package == nil) assert(package == nil)
assert(require("_G") == _G) assert(require("_G") == _G)
for _, name in ipairs({"io", "os", "debug", "channel", "coroutine", "dofile", "loadfile", for _, name in ipairs({"io", "debug", "channel", "ch", "coroutine", "dofile", "loadfile",
"load", "loadstring", "getfenv", "setfenv", "collectgarbage", "module", "load", "loadstring", "getfenv", "setfenv", "collectgarbage", "module",
"getmetatable", "setmetatable", "rawget", "rawset", "newproxy", "print", "_printregs"}) do "getmetatable", "setmetatable", "rawget", "rawset", "newproxy", "print", "_printregs"}) do
assert(_G[name] == nil, name) assert(_G[name] == nil, name)
end end
for _, name in ipairs({"io", "os", "debug", "channel", "coroutine", "package", "escape"}) do for _, name in ipairs({"io", "debug", "channel", "ch", "coroutine", "package", "escape"}) do
assert(not pcall(require, name), name) assert(not pcall(require, name), name)
end end
for _, name in ipairs({"math", "string", "table"}) do for _, name in ipairs({"math", "string", "table", "os"}) do
assert(require(name) == _G[name], name) assert(require(name) == _G[name], name)
end end
for _, lib in ipairs({os, require("os")}) do
for _, name in ipairs({"clock", "date", "difftime", "time"}) do
assert(type(lib[name]) == "function", "os." .. name)
end
for _, name in ipairs({"execute", "exit", "getenv", "remove", "rename", "setenv", "setlocale", "tmpname"}) do
assert(lib[name] == nil, "os." .. name)
end
end
assert(string.dump == nil and ("").dump == nil and require("string").dump == nil) assert(string.dump == nil and ("").dump == nil and require("string").dump == nil)
assert(math.randomseed == nil and require("math").randomseed == nil) assert(math.randomseed == nil and require("math").randomseed == nil)
local helper = require("xray.test") local helper = require("xray.test")
@@ -1144,8 +1152,8 @@ func TestProgramPrivilegesAreCompileTimeSnapshot(t *testing.T) {
} }
check := func(L *glua.LState) { check := func(L *glua.LState) {
t.Helper() t.Helper()
if got := L.GetGlobal("os").Type() == glua.LTTable; got != privileged { if got := L.GetField(L.GetGlobal("os"), "execute").Type() == glua.LTFunction; got != privileged {
t.Fatalf("os available = %t, want compile-time value %t", got, privileged) t.Fatalf("os.execute available = %t, want compile-time value %t", got, privileged)
} }
} }
factory := program.NewStateFactory(time.Second, nil, nil) factory := program.NewStateFactory(time.Second, nil, nil)