Malla文档

安全模型

沙箱化画布、不使用 eval、服务端密钥、行规则、限流和出站策略。

开发者指南

Malla 在客户密钥旁边运行着不可信的内容、用户公式和访客输入。以下这些边界让它们彼此隔离。

沙箱画布画板在独立的源上渲染,因此用户内容永远无法接触编辑器会话。
不使用 eval表达式经过解析并解释执行,有白名单和硬性限制。
服务端密钥加密存储,只在 api Worker 中解密,绝不发送到任何浏览器。
行规则访客和工作流对原生表的每一次读写都会经过检查。
出站策略服务端请求会拦截私有地址、先解析 DNS、限制时间和大小。
限流登录、注册、表单、查询、端点和集成都有限流。

两类用户,绝不混用

编辑器用户和站点访客使用不同的表、不同的会话 cookie 和不同的签名密钥。编辑器会话是 HTTP-only、Secure、SameSite=Lax 的 cookie,并带有 CSRF 检查;密码用 scrypt 哈希。访客会话的作用域限定在客户的域名上,存放在站点自己的数据库中。

授权

  • 每个 api 路由都会检查调用者在该站点上的角色;未知站点和无权访问的站点都返回 404。
  • 发布到生产环境、修改 slug、管理域名和写入集成都需要管理员。
  • 实时房间会验证短期令牌和页面所属站点;查看者只读,内容编辑者只能修改文本。
  • Realtime 在存储或转发每个更新之前,都会按结构定义进行校验。

表达式

没有 eval,也没有 new Function。解释器拒绝 window、document、globalThis、constructor、__proto__ 和 prototype,不支持赋值和循环,并限制源码长度、深度、求值节点数、字符串和数组大小。服务端也用同一个解释器求值行规则和页面访问规则。

浏览器不可信

客户端工作流和绑定可以被访客读取和修改,因此它们从不拥有任何权限。页面访问在服务端强制执行,受限页面的客户端查询要通过同样的关卡,写入则通过服务端工作流和行规则。在规则中,匿名 user 带有 id: NaN,因此所有权检查绝不会匹配没有所有者的行。

出站请求

集成只能访问它们声明的主机。服务端请求要求 HTTPS,通过 DNS-over-HTTPS 解析主机名,拦截私有、回环和链路本地地址(重定向会重新检查),并限制时间和响应大小。runJs 在没有绑定、没有密钥的 Worker Loader 隔离环境中运行。

样式和 HTML

可能跳出规则的样式值会被拒绝;属性名会经过校验。渲染器会转义文本并净化 URL。富文本以结构化 JSON 存储,绝不存为原始 HTML。站点自定义代码只在已发布站点上运行,绝不在编辑器中运行。

防滥用

表单使用 Turnstile、蜜罐以及按 IP 和按表单的限制,并以哈希形式存储 IP。公共端点、客户端查询、登录和注册使用 Cloudflare 限流。