向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運作案例。
參考資料
- WordPress Developer Resources:WP-CLI指令列表
- WordPress Developer Resources:WP-CLI全域參數
- WordPress Developer Resources:wp post create
- OpenBSD manual pages:sshd_config
※伺服器、SSH與WordPress配置依服務供應商而異。修改設定前,請確認官方手冊與維護合約,並準備失去連線時的復原方法。

