跳转到内容
查看源码

能力与安全

Entelechy 把权限分成两层:

  1. Kernel 能力(requires { … }):一个 Kernel 能对 Field、输入和时间做什么。由编译器检查,由会话授予。
  2. Host 权限(--allow …):场景能接触到的文件和剪贴板。由运行场景的人决定,永远不能通过协议扩大。
能力 授予
field.read 读取输入 Field(sample、value、size…)
field.write 创建并写入输出 Field(包括图片)
input.read 读取指针、按键、文字输入、手柄等
time.read 读取场景时钟(time()、clock())
kernel demo.tint@1 {
requires { field.read; field.write; }
...
}

缺少能力时编译器直接告诉你该加什么(真实输出):

{"error":{"column":102,"line":1,"message":"writing an output needs `field.write`; add it to `requires`"},"id":1}

运行场景的人可以限定会话可授予的能力(默认全部):

终端窗口
entelechy serve scene.esn --grant field.read,time.read

要求未授予能力的 Kernel 在准备时被拒绝,之前运行的继续运行(真实输出):

rejected /tmp/fk/kernels/rings.ent: demo.rings@1 requires field.write, which this session does not grant

render、serve、bench 和 Player 都接受 --grant;协议的 status 在 grants 中返回当前可授予的能力。

写法 允许
--allow file.write=<dir> 写到文件的输出(to "…")落在该目录及其子目录;在改变它们的求值提交之后才写。没有它什么都不写
--allow file.delete=<dir> to files 输出在该目录删除和重命名文件
--allow file.read=<dir> served 场景的输入读取该目录下的文件
--allow clipboard.read、--allow clipboard.write Player 中的场景读写系统剪贴板(其他地方场景的剪贴板是会话自己的)
--allow-origin <origin> 允许该网页来源连接 WebSocket

render、serve 和 Player 接受三种文件权限。回放中用 allow file.write <dir>,写入的内容只保留在本次运行中,不会落盘。

当 Agent 通过 serve 驱动场景时:

  • 读取只限于场景首次加载时的目录(场景、它放置的图、它使用的文件、输入读取的文件)、包目录,以及 --allow file.read 给出的目录——按解析链接和 .. 之后的落点判断。compose 写入的新文档不会扩大这个范围。
  • 写入需要 --allow file.write。compose 只写场景自己的 .ent、.esn、.replay 文件(在场景目录下,不在包目录中)。
  • Socket/WebSocket:WebSocket 升级只接受本机页面(localhost、127.0.0.1、[::1])、非浏览器客户端或 --allow-origin 指定的来源,其余返回 403。从文件打开的页面来源是 null,需要 --allow-origin null。
  • 预算:Agent 发送的内容先按 Host 预算(--memory、--work)计费再执行;socket 请求最大 256 MiB;一个连接有 64 个未读答复时停止读取它,不读答复的对端只会拖慢自己。

served 场景能接触到的,就是运行它的人给出的。 原因:Agent 能读的文件它就能发出去;而你访问的任何网页都能连到你机器上的 socket。(docs/DECISIONS.md)

  • 循环预算:运行时计数的循环整体运行,由 --work 约束;Kernel 清单的 budget 给出一个元素可执行的迭代数。
  • 无递归:函数永远不会到达自己,循环调用被拒绝并指出环。
  • 效果是数据:Kernel 的效果(写文件等)是 Host 在提交之后执行的数据,而不是 Kernel 直接做的副作用。
  • 仓库中 crates/interface/entelechy/tests/hostile.rs 测试恶意输入。