0Pricing
Lua Academy · 课时

沙箱化插件执行

使用 setfenv/load 和自定义 _ENV 在受限环境中运行插件。

沙箱化插件执行 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。

为什么要对插件使用沙箱?

不受信任的插件代码可能调用危险函数(os.execute、io.open、load),或访问应用程序的私有状态。沙箱可以限制代码能够执行的操作。

Lua 5.2+ 中的自定义 _ENV

在 Lua 5.2+ 中,每个代码块的全局环境都是 _ENV。使用受限的 _ENV 加载代码块,以限制其访问权限。

local function sandbox(code, env)
  local chunk, err = load(code, "sandbox", "t", env)
  if not chunk then return nil, err end
  return pcall(chunk)
end

构建安全环境

创建一个白名单环境,其中只包含安全的标准库函数。

local safeEnv = {
  print  = print,
  type   = type,
  pairs  = pairs,
  ipairs = ipairs,
  tostring = tostring,
  tonumber = tonumber,
  table  = {insert=table.insert, concat=table.concat, sort=table.sort},
  string = {format=string.format, find=string.find, match=string.match},
  math   = math,
}

阻止危险函数

明确排除:os、io、load、loadfile、dofile、require、debug。不要将它们复制到 safeEnv 中。

在沙箱中加载文件

加载插件文件,并在沙箱环境中执行它。

local function sandboxFile(path, env)
  local chunk, err = loadfile(path, "t", env)
  if not chunk then return nil, err end
  local ok, result = pcall(chunk)
  if not ok then return nil, result end
  return result
end

提供 API 访问权限

只将安全的方法加入环境,为沙箱中的插件提供受限的应用程序 API 访问权限。

local pluginEnv = setmetatable({
  app = {
    on       = function(e,f) app:on(e,f) end,
    emit     = function(e,...) app:emit(e,...) end,
    log      = function(msg) app:log(msg) end,
  },
}, {__index = safeEnv})

防止访问 _ENV

不要将 _G、_ENV 或 load 加入沙箱。这些内容可以让代码逃离受限环境。

使用 debug.sethook 进行指令计数

通过统计已执行的指令,并在达到限制后中止执行,来防止无限循环。

local function withLimit(fn, maxInstructions)
  local count = 0
  debug.sethook(function()
    count = count + 1
    if count > maxInstructions then
      error("Instruction limit exceeded")
    end
  end, "", 100)
  local ok, err = pcall(fn)
  debug.sethook()
  return ok, err
end

内存限制

将指令计数与定期执行的 collectgarbage("count") 检查结合起来,在内存使用量超过阈值时中止执行。

捕获输出

将沙箱环境中的 print 替换为自定义函数,把输出捕获到缓冲区,而不是写入标准输出。

需要避免的沙箱逃逸方式

已知的逃逸途径包括:debug.getupvalue、对标准对象使用 getmetatable,以及对危险代码使用 coroutine.wrap。请仔细检查环境中的所有条目。

沙箱问题

如何防止沙箱中的代码调用 os.execute?

回顾:插件沙箱

创建只包含安全 API 的白名单 _ENV。使用 load(code, name, "t", safeEnv) 加载插件代码。使用指令计数来防止无限循环。切勿将 load、debug 或 _G 包含在沙箱中。

常见问题解答

「沙箱化插件执行」课时是免费的吗?

是的 — 「沙箱化插件执行」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「沙箱化插件执行」这节课中我会学到什么?

使用 setfenv/load 和自定义 _ENV 在受限环境中运行插件。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「沙箱化插件执行」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Lua Academy 课中编写并运行代码吗?

能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 发现和加载插件
  2. 插件 API 和钩子系统
  3. 沙箱化插件执行
  4. 版本管理和依赖管理
← 返回 Lua Academy