如何制作让AI安全使用WP-CLI的受限制指令包装器

描绘一道门筛选旅宿经营者与AI对WordPress的操作,只让安全操作通过的插画 AI 网站管理

向AI交代「不要使用删除指令」很重要,但光靠这段文字,无法保护正式网站。因为对委托的理解有误、输入错误,或后来追加的指示等,都可能让AI选择非预期的指令。

因此,我们不让AI直接执行WP-CLI,而是在中间设置一个只接受少量、经管理者核准操作的入口。这个入口就是「受限制的指令包装器」。

本文旨在解释运作机制。导入前,请通过将WP-CLI交给AI之前的准备确认权限、备份与测试环境。变更服务器用户或权限的工作,应委托服务供应商或服务器管理者处理。

什么是受限制的指令包装器

一般WP-CLI不只可查看文章,也有删除、更新、数据库操作与执行任意PHP代码等功能。官方指令列表中也包含wp db、wp eval、wp search-replace、wp user等需要谨慎处理的指令。

受限制的指令包装器不会把AI输入的字符串直接传给wp。例如,只接受以下三个自订操作名称。

  • site-status:确认WordPress的版本与状态
  • plugin-status:确认插件列表
  • post-list:确认已发布文章或草稿列表

包装器内部将各项操作转换成管理者已确认的WP-CLI指令。不符合的操作名称会返回错误,不予执行。

文字规则与技术限制的用途不同

在AGENTS.md或CLAUDE.md中,写下「一开始只进行读取」「发布、删除与更新须经人核准」等作业规则,有助于AI与人共享判断标准。

另一方面,受限制的指令包装器会在执行路径上阻挡未获允许的操作。

旅宿经营者的委托
  ↓
Codex・Claude Code
  ↓
受限制的指令包装器 ── 拒绝未获允许的操作
  ↓
固定的WP-CLI指令
  ↓
WordPress

基本做法是结合文字规则、指令包装器、OS与WordPress权限,以及人工确认。单靠一个包装器,并不能保证安全。

安全设计原则

1. 从允许清单开始

不要只禁止危险指令,而应采用只允许已核准操作的方式。WP-CLI也有来自额外软件包或插件的指令,因此禁止清单可能漏掉未知操作。

一开始只确认状态,再逐项新增有需要的操作。

2. 不直接接收WP-CLI指令字符串

如果能向包装器传入像wp post list ...这样的自由指令字符串,检查就容易出现漏洞。应接收post-list等自订操作名称,并在包装器内固定实际指令与参数。

不得用eval重新执行输入字符串,也不得把整段输入传给shell。

3. 固定目标网站

WP-CLI有可变更目标的全局参数。不要让外部自由传入--path、--url、--ssh、--require、--exec等参数;WordPress位置与目标URL应由管理者固定。

4. 使用专用执行用户

不要与AI共享平常的管理者账号或root。应准备一个只具备确认WordPress所需权限的专用用户,并移除交互式shell、文件写入与传输等不必要的权限。

即使指定WordPress用户,也应限定为作业所需权限,而不是管理者权限。

5. 留下记录并限制数量

记录执行日期与时间、操作名称、成功或失败,以及目标ID,但不在日志中记录文章正文、设置值或身份验证信息。每次执行的操作数量或取得的数据条数,也应设置上限。

只读指令包装器的最小示例

以下是用于说明机制的虚构环境示例,没有包含实际WordPress位置或执行用户。请勿直接放入正式环境;应由管理者依环境设计拥有者、权限、日志与执行方式。

#!/usr/bin/env bash
set -euo pipefail

readonly PATH=/usr/local/bin:/usr/bin:/bin
readonly WP=/usr/local/bin/wp
readonly SITE=/srv/example/wordpress

action=${1:-}
shift || true

# 拒绝所有非预期的额外参数
if (( $# != 0 )); then
  echo "不可使用额外参数" >&2
  exit 64
fi

case "$action" in
  site-status)
    "$WP" --path="$SITE" core version
    "$WP" --path="$SITE" core is-installed
    ;;
  plugin-status)
    "$WP" --path="$SITE" plugin list \
      --fields=name,status,version --format=table
    ;;
  post-list)
    "$WP" --path="$SITE" post list \
      --post_type=post \
      --post_status=publish,draft \
      --fields=ID,post_title,post_status \
      --posts_per_page=20 \
      --format=table
    ;;
  *)
    echo "这项操作未获允许" >&2
    exit 64
    ;;
esac

重点是不像wp "$@"那样,把整段外部输入交给WP-CLI。可执行文件、WordPress位置、子指令与选项,都在包装器端固定。

通过SSH时,也要固定入口

若让AI通过SSH连接至VPS,应分开使用AI专用密钥与用户,并考虑采用连接后不允许开启自由shell的设计。OpenSSH的ForceCommand能以固定指令取代客户端指定的指令。

不过,单靠ForceCommand并不会阻止端口转发或代理转发。OpenSSH官方手册也说明,不需要这些功能时,必须通过DisableForwarding等设置另外停用。

SSH设置有误,可能让管理者自己也无法连接。应保持现有连接,进行设置检查与另一个工作阶段的连接测试,并由网站制作公司或管理者设置。

允许建立草稿时的额外条件

读取之后,若要允许制作文章,也不要开放自由使用wp post create,而应另设一个「建立一篇新文章草稿」的专用入口。

  • 将post_type固定为post
  • 将post_status固定为draft
  • 每次只处理一篇
  • 检查slug的字符种类与长度
  • 将可读取正文文件的位置限制在专用目录内
  • 从已核准的候选项目中选择分类ID
  • 建立后回报文章ID与预览位置
  • 将变更为publish的操作分成另外须经核准的程序

WP-CLI的wp post create可以指定文章状态,因此能在包装器端固定为draft。不过,即使是草稿,也可能存储不适当的内容或个人资料。创建草稿后,务必由人在管理界面确认。

不应制作的指令包装器

以下这类实现,即使名为「安全包装器」,仍无法提供充分限制。

# 将任何外部输入都传给WP-CLI
wp "$@"

# 把字符串再次当作shell解读
eval "$SSH_ORIGINAL_COMMAND"

也应避免「没有包含delete这个字就允许」之类的检查方式,因为这会漏掉其他更新路径、缩写或额外指令。

导入前的确认清单

  • 执行用户与管理者不同
  • 已核准操作名称以外的名称会返回错误
  • 拒绝额外参数、未知选项与多笔操作
  • WP-CLI可执行文件与WordPress位置已固定
  • 没有使用eval或自由shell
  • 无法调用PHP执行、数据库操作、设置显示、更新或删除
  • SSH的shell与各种转发已受限制
  • AI端无法改写包装器与配置文件
  • 留有不包含秘密信息的审计日志
  • 已在测试环境确认「允许」与「拒绝」两种情况
  • 不只确认备份,也确认复原方法
  • 发布、更新与删除,会停在由人核准的阶段

给AI的委托示例

在这个网站,不要直接执行WP-CLI,只能使用管理者准备的
受限制指令包装器。

请先确认可用的操作名称,这次只使用只读的
site-status、plugin-status、post-list。

不要进行未获允许的操作、使用额外参数、变更设置、更新、删除或
发布。请回报已执行的操作名称与结果,
不要在回答中显示个人资料或秘密信息。

这段委托文字是协助判断的规则,应搭配执行路径端的限制使用。

总结

让AI协助使用WP-CLI时,不只要用文字禁止危险操作,也要准备一个只有已核准操作才能实际通过的入口。

一开始从大约三项只读操作开始,也要测试确实能拒绝操作。之后,再视需要逐项新增「建立一篇草稿」「确认公开页面的HTTP响应」等专用操作。实际流程请见从备份到文章发布、HTTP与画面确认的步骤。

若第一次接触WP-CLI,请先阅读什么是WP-CLI?让AI协助WordPress前应知道的基础与安全入门。AI作业整体规则整理于使用AI管理WordPress的安全规则,文章列表请见给旅宿经营者的网站营运指南。

如何在实际运作中组合这些方法,并将失败经验纳入规则,请见猫宿研究所的AI与WP-CLI运作案例。

参考资料

※服务器、SSH与WordPress配置依服务供应商而异。修改设置前,请确认官方手册与维护合约,并准备失去连接时的复原方法。

已复制标题与网址