Ruby 沙箱与集成脚本语言

发布于 2024-12-22 19:33:19 字数 1740 浏览 0 评论 0 原文

我目前正在使用 Ruby 开发基于文本的游戏引擎,该应用程序分为 /lib 中的 Ruby 代码和 /data 中的 YAML 数据,该数据在游戏需要时加载。我想允许数据文件包含基本脚本,主要是在事件/观察者模型中。但是,我还希望用户能够生成和共享自定义场景,而不必担心脚本中嵌入的恶意代码。

附录:我最初的计划是将用户创建的内容分为两种类型,“模块”仅包含数据(因此安全)和添加附加功能的插件(但显然不安全) 。与桌面游戏进行类比,模块就像已发布的冒险场景和内容,而插件将是包含附加规则和系统的规则手册。

示例脚本(语法当然可能会根据解决方案进行更改):

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

从安全角度来看,如果脚本是严格选择加入的,可能通过包含一些 DSL 的 mixin 来实现,那将是理想的选择,例如:

class Frog
  include Scriptable

  def jump; ... ; end # this can be called from a script
  allow_scripting :jump

  def ribbit; ... ; end # this cannot be called from a script
end

我看过 三个四个选项,但我不确定哪种是最好的方法:

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

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

    缺点:对安全问题或沙箱不太熟悉,还没有找到任何似乎合适的现成解决方案。

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

    优点:Ruby 和 Lua 是基于 C 的,因此绑定应该相当简单。 Lua 是一种相当流行的语言,因此如果我以后遇到问题,可以提供帮助。安全,因为我没有专门绑定的任何功能都无法从脚本中获得。

    缺点:现有的 Ruby-Lua 绑定似乎是单向的、陈旧且维护不善,或者两者兼而有之。将一种脚本语言嵌入到另一种脚本语言中似乎有点狡猾。

  3. 使用 Ruby 解释器实现自定义脚本语言。我一直在尝试 Treetop,创建一个足以满足脚本需求的简单语法应该不会太难。< /p>

    优点:无需嵌入其他语言。只有我专门实现的功能才可用于脚本。

    缺点:杀伤力过大。 “不建在这里”综合症。可能会出现一堆可怕的错误。

  4. 使用特定于域的语言完全用 Ruby 实现数据文件。

    优点:简单易用。

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

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

编辑2011年12月23日:添加了DSL的第四个选项,在顶部添加了带有附加想法/上下文的“附录”。

I am currently working on a text-based game engine in Ruby, with the app separated into Ruby code in /lib and YAML data in /data, which is loaded when needed by the game. I want to allow the data files to contain basic scripts, mostly in an event/observer model. However, I also want users to be able to generate and share custom scenarios without having to worry about malicious code embedded in the script.

Addendum: My original plan was to have user-created content separated into two types, "modules" which were data-only (and thus safe) and plugins which added additional functionality (but obviously were not safe). To make an analogy to tabletop gaming, modules would be like published adventure scenarios and content, and plugins would be rulebooks containing additional rules and systems.

Sample script (syntax of course subject to change based on solution):

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

From a security standpoint, it would be ideal if scripting was strictly opt-in, probably through an included mixin with a little DSL, e.g.:

class Frog
  include Scriptable

  def jump; ... ; end # this can be called from a script
  allow_scripting :jump

  def ribbit; ... ; end # this cannot be called from a script
end

I've looked at three four options, but I'm not sure which is the best approach to take:

  1. Use Ruby scripting, but in a sandbox of some kind.

    Pros: Very familiar with Ruby, no need for "glue" code or issues integrating objects between languages.

    Cons: Not very familiar with security issues or sandboxing, haven't found any out-of-the-box solutions that seem to fit.

  2. Implement Embed another scripting language, e.g. Lua.

    Pros: Ruby and Lua are C-based, so bindings should be reasonably simple. Lua is a reasonably popular language, so help available if I run into issues later. Secure, since any functionality I don't specifically bind will be unavailable from scripts.

    Cons: Existing Ruby-Lua bindings seem to be one-way, old and poorly maintained, or both. Seems a mite dodgy to embed a scripting language inside another scripting language.

  3. Implement a custom scripting language with Ruby interpreter. I've been experimenting with Treetop, and it shouldn't be too hard to make a simple grammar that would suffice for the scripts.

    Pros: No need to embed another language. Only functionality I've specifically implemented will be available to scripts.

    Cons: Overkill. "Not built here" syndrome. Probably horrible nest of bugs waiting to happen.

  4. Implement the data files entirely in Ruby, using a domain-specific language.

    Pros: Simple and easy.

    Cons: No user-created data is trustable.

I am also open to other suggestions not on that list that I may not have thought of. What is the best solution to safely implement scripts embedded in data files?

Edit 2011年12月23日: Added fourth option with DSL, added "addendum" at top with additional thoughts/context.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

儭儭莪哋寶赑 2024-12-29 19:33:19

您可以考虑使用 Shikashi gem,它允许您创建沙箱并定义允许的方法调用的白名单个别对象。

You might consider using the Shikashi gem, which allows you to create sandboxes and define a whitelist of allowed method calls on individual objects.

深居我梦 2024-12-29 19:33:19

考虑使用 jRuby 而不是 Ruby。 Java 最初是为了支持移动代码(早在机顶盒时代)而实现的,并且具有经过充分测试的 嵌入,这可能有助于将游戏核心与用户应用程序分开,虽然我不知道此时它的鲁棒程度如何。

当然,jRuby 就是 Ruby!

Consider using jRuby instead of Ruby. Java was originally implemented to support mobile code (back in the set-top days) and has a well-tested security model/implementation that could, I suspect, wrap enough of jRuby to keep user scripts/classes from creating havoc with the rest of the game system. jRuby supports embedding, as well, which may help separate the game core from the user applications, although I do not know how robust it is at this time.

And, of course, jRuby is Ruby!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文