Ruby沙箱化与集成脚本语言

我目前正在使用 Ruby 构建一个基于文本的游戏引擎,应用程序将分为 /lib 中的 Ruby 代码和 /data 中的 YAML 数据,当游戏需要时加载。我希望允许数据文件包含基本的脚本,主要采用事件/观察者模型。然而,我也希望用户可以生成和分享自定义场景,而无需担心嵌入脚本中的恶意代码。

附言:我的原始计划是将用户创建的内容分为两种类型,"模块"是仅包含数据的(因此是安全的),而插件则添加了额外的功能(但显然不安全)。为了做出桌面游戏的类比,模块就像发布的冒险场景和内容,而插件则是包含额外规则和系统的规则书。

示例脚本(当然,语法可能会因解决方案而改变):

---
Location:
  observers:
    on_door_open: |
      monster = spawn_monster(:goblin);
      monster.add_item(random_item());
      monster.hostile = true;

从安全角度来看,如果脚本严格地选择性加入,最理想的情况是通过包含一些 DSL 的混合授权,例如:

class Frog
  include Scriptable

  def jump; ... ; end # 可以从脚本中调用此函数
  allow_scripting :jump

  def ribbit; ... ; end # 不能从脚本中调用此函数
end

我看了三种四种选择,但我不确定应该采取哪种方法:

  1. 使用 Ruby 脚本,但在某种沙盒中。

    优点:非常熟悉 Ruby,不需要“胶合剂”代码或在语言之间集成对象的问题。

    缺点:对于安全问题或沙盒不太熟悉,还没有找到任何看起来符合要求的开箱即用的解决方案。

  2. 嵌入另一种脚本语言,例如 Lua。

    优点:Ruby 和 Lua 基于 C,因此绑定应该相对简单。Lua 是一种相当受欢迎的语言,因此如果在以后遇到问题,可以获得帮助。安全,因为我没有明确绑定的任何功能将无法从脚本中使用。

    缺点:现有的 Ruby-Lua 绑定似乎是单向的、旧的并且维护得很差。嵌入一种脚本语言到另一种脚本语言中似乎有点不靠谱。

  3. 通过 Ruby 解释器实现自定义脚本语言。我一直在尝试 Treetop,并且制作一个足够简单的语法可以满足脚本的需求。

    优点:无需嵌入另一种语言。只有我明确实现的功能可以在脚本中使用。

    缺点:过于复杂和繁琐。“非本构建”综合症。可能存在许多静态错误。

  4. 使用特定领域语言完全在 Ruby 中实现数据文件。

    优点:简单易行。

    缺点:不信任用户创建的数据。

我也愿意接受列表中没有想到的其他建议。最安全有效地实现嵌入数据文件的脚本是什么解决方案?

原文链接 https://stackoverflow.com/questions/8619422

点赞
stackoverflow用户272441
stackoverflow用户272441

建议使用 jRuby 代替 Ruby。Java最初实现是为了支持移动代码(在机顶盒时代)并且有一个经过充分测试的 安全模型/实现 ,我猜测可以包装足够的 jRuby ,以防止用户脚本/类与游戏系统的其余部分创建大量麻烦。jRuby还支持 嵌入,这也可以帮助将游戏核心与用户应用程序分开,虽然我不确定它在这个时候有多么强大。

当然,jRuby就是Ruby!

2011-12-24 01:26:09
stackoverflow用户1062679
stackoverflow用户1062679

你可以考虑使用 Shikashi gem ,它允许你创建沙盒并在单个对象上定义被允许的方法调用白名单。

2012-01-02 19:52:39