返回资讯中心
外部精选
软件工程
#开发者实时流

Hatamoto 推出 WASM 沙箱插件架构,插件写入需经变更集审核发布

来源标题:Plugins with no writes to the live site.WASM sandboxes and reviewable changesets

Hatamoto 发布新的插件架构:插件运行在 WebAssembly 沙箱中,没有任何可直接写入线上站点的宿主函数,内容只能先写入变更集,经站点所有者预览后发布、丢弃或整体回滚。只有所有者授予长期批准后,后台任务才能免审发布指定字段更新。该变更集模型已合并至主分支并在 hatamoto.dev 运行,将在 48 小时内随 core 1.1.0 和 SDK 0.17 进入自托管安装。

Hacker News 最新zenincognito2026/11/4 · 2 天前24 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

WordPress 插件是以 PHP 运行在核心同一进程中,拥有整个数据库。Hatamoto 插件运行在 WASM 沙箱中,只能通过变更集写入内容,由站点所有者或一项常设批准来发布。

Hatamoto 插件运行在 WebAssembly 沙箱中,没有任何可写入线上站点的宿主函数。它在运行期间将输出暂存到变更集中;所有者应用该变更集预览站点,然后发布、丢弃,或稍后整体回滚。只有所有者授予的常设批准,才允许后台运行在没有该审查的情况下发布类型化字段更新。

在本文中,我将介绍 hatamoto 插件的整体架构、它如何工作,以及为什么这种“两个房间”的实现把安全性放在首位。

WordPress 插件是以 PHP 加载到与核心相同的进程中,在每个请求上运行,拥有全局 $wpdb、文件系统和出站网络。以这种方式运行站点近二十年、没有可开启的沙箱之后,我构建了这套机制,它优于现状。

变更集模型已合并到 main,并运行在 hatamoto.dev 上;它将随 SDK 0.17 在 core 1.1.0 中进入自托管安装,后者将在未来 48 小时内发布。

在开发者参考中,$wpdb 可以读取 WordPress 数据库中的任何表,其 insert、update 和 delete 方法会写入调用所指定的任何表,query 可运行任意 SQL,包括 DROP。$wpdb->users 和 options 表与其他表并无不同。同一份 PHP 可以打开文件、调用任意服务器、创建用户或更改角色。

没有权限列表。wp-config.php 在每个非缓存提供的页面视图上都会被加载,运维人员可以在其中添加常量来阻止外部 URL 请求或禁用插件文件编辑器。

这种开放性正是 WordPress 如此易于扩展的原因,也是风险所在。在 Patchstack 的 2026 年报告中,2025 年披露的漏洞中有 46% 在披露时没有修复;对于被利用最严重的那些,从披露到被利用的加权中位时间为五小时,而访问控制失效是被利用最多的类别。

2024 年 6 月,WordPress.org 上的五个插件发布了带有注入代码的更新,这些代码试图创建管理员账户并将其详细信息发送到攻击者的服务器。该更新继承了插件已有的所有写入能力。Hatamoto 插件没有任何创建用户或触及身份验证的函数,因此同样的代码无法创建账户,它暂存的任何内容都会留在一个没有批准的变更集中,而版本变更会使其常设批准失效。它仍会保留插件的其他授权,例如读取以及对其所列主机的 http.fetch。加固供应链本身留待后续 ADR 处理,将单独解决。

2024 年 8 月,Patchstack 公布了 LiteSpeed Cache 中的 CVE-2024-28000,影响超过 500 万个站点:其用户模拟功能中的弱哈希可被暴力破解,之后未认证的访客就能创建管理员。Hatamoto 没有授予角色的宿主函数,因此插件代码中的漏洞无法被转化为管理员账户;最坏情况下它只会暴露该插件被授予的内容。

2024 年 2 月,Wordfence 披露了 Ultimate Member 中的 CVE-2024-1071,这是一个未认证 SQL 注入,影响 20 万个站点,可提取密码哈希。被授予 db 的 Hatamoto 插件会获得自己的 Postgres 角色,该角色拥有一个 schema,对核心表没有任何权限;插件 SQL 中的注入只会落在插件自己的表中。

2020 年 9 月,File Manager 插件(70 万安装量)发布了一个库连接器,允许未认证访客上传文件并执行命令。Hatamoto 插件没有文件系统:没有挂载任何东西,也没有宿主函数接受路径。一次运行唯一能读取的文件是所有者附加的上传文件,通过 upload.read 读取。

在 Hatamoto 中,插件是使用 Extism 在 wazero 上运行的 Wasm 模块。除 Extism 的内置功能外,只有一个宿主导入 hm_call,其背后的每个函数都要经过权限检查,除了运行函数——它们按运行的阶段进行检查。默认不授予任何权限,没有相应授权的调用会返回 capability_denied。

limits.memory_pages 默认将每个线性内存限制为 256 页(16 MiB)。每次调用都有截止时间,过滤器 and 模板函数默认 250 毫秒,动作、cron 和路由默认 10 秒。wazero 没有燃料计量,因此截止时间就是机制。limits.max_instances 默认将活动实例限制为 4 个,最多 16 个。

钩子失效开放。陷入陷阱、内存耗尽或超时的过滤器会保持原值不变,该实例被丢弃。连续三次则将该钩子关闭 30 秒。

唯一的网络是 http.fetch,由宿主执行(media.import_url 通过同一客户端下载)。宿主解析名称,拒绝私有、回环、链路本地、CGNAT 和保留地址的应答,拨号已检查的 IP 以防 DNS 重绑定,并在最多 5 次重定向跳转中重复此过程。

所有者从管理后台启动一次运行,提供插件的输入、它可抓取的主机,以及(如需要)一个上传文件。然后宿主反复调用 on_run_step,参数为 { "run_id", "phase", "cursor" };每次调用有自己的截止时间,默认 10 秒。

抓取阶段有网络、无站点数据:对所有者确认的主机执行 http.fetch(cron 启动的运行获得清单中的 allowed_hosts,绝不会是 *)、upload.read、buffer.put 和 media.import_url。转换阶段有站点数据、无网络:buffer.get、buffer.list、site.info、已发布内容的读取、entities.slug_taken 和 changeset.*。任何不在该阶段列表中的操作都会返回 phase_denied,插件自己的 kv 和 db 在两个阶段中都被拒绝。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →