WP-CLI × Claude Code 實測:七個坑、一個 SQL injection,和一組能救你的護欄
WP-CLI 搭 Claude Code 自動化 WordPress,實際做起來會撞到什麼?我從零架了一個站來實測:環境三連坑、SQLite 讓 wp db export 靜默失敗、官方 Plugin Check 跑出 20 項違規含真的 SQL injection。附可直接複製的護欄三件套,以及我自己寫錯的那個 fail-open 漏洞。
我沒有 WordPress 網站。這篇的第一件事,就是為了寫它而從零架了一個。
因為這個題目最爛的寫法,就是把官方文件的指令抄一遍,配上「三步驟輕鬆自動化」的標題。真正有用的東西不在文件裡,在你安裝到一半炸掉的那些地方。所以我裝了 PHP、裝了 WP-CLI、架了 WordPress 7.0.2、寫了外掛、寫了護欄,然後把每個絆倒我的地方記下來。
七個坑,一個真的 SQL injection,還有一個我自己寫的、差點放行 DELETE FROM wp_posts 的資安漏洞。以下全部有實測輸出。
WP-CLI 裝起來就三個坑:環境根本沒那麼好裝
我用 brew install php wp-cli。第一次直接失敗,而且失敗得很陰險:
brew install php wp-cli 2>&1 | tail -25
回報成功,實際上整包沒裝(brew 鎖衝突)。原因是 pipe 後面接了 tail,exit code 被 tail 吃掉了。這個坑對 AI agent 特別致命,因為它會以為裝好了,繼續往下做。修法是 set -o pipefail。
裝好之後,wp 一跑就吐:
PHP Deprecated: Case statements followed by a semicolon (;) are deprecated in .../wp-cli/2.12.0/.../react/promise/src/functions.php
這不是我的錯,是 WP-CLI 穩定版停在 2.12.0 已經 14 個月,而 PHP 已經走到 8.5。順帶一提,新的 wp ai、wp ability 指令目前只存在 nightly 的 2.13.0-alpha,brew 裝不到。
接著 wp core download:
cURL error 77: error adding trust anchors from file: /usr/local/etc/openssl@3/cert.pem
ca-certificates 明明裝了,但 openssl@3 少了那條 symlink。補上就好:
ln -sfn /usr/local/etc/ca-certificates/cert.pem /usr/local/etc/openssl@3/cert.pem
HTTPS 通了,下一個:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
PHP 預設 128MB 不夠解壓 WordPress 核心。最後我把三件事包成一個 wrapper 才穩定:
php -d error_reporting="E_ALL & ~E_DEPRECATED" -d memory_limit=512M /usr/local/bin/wp "$@"
這四段全是文件不會寫的東西,但你不解決就一步都走不下去。
先有雞還是先有蛋:WP-CLI 裝 SQLite 的安裝悖論
我不想在機器上留一個常駐的 MySQL,所以走 SQLite。結果:
wp plugin install sqlite-database-integration → Error: 建立資料庫連線時發生錯誤
wp plugin install 執行前要先連資料庫,而我要裝的正是提供資料庫的那個外掛。
繞法是直接抓 zip,然後這步官方文件講得很含糊:複製 db.copy 成 wp-content/db.php 之後,裡面有兩個佔位符要手動替換。
sed -i '' "s#{SQLITE_IMPLEMENTATION_FOLDER_PATH}#$(pwd)/wp-content/plugins/sqlite-database-integration#g" wp-content/db.php
sed -i '' "s#{SQLITE_PLUGIN}#sqlite-database-integration/load.php#g" wp-content/db.php不換這兩個,wp core install 就一直失敗。
最毒的雷:SQLite 站上 wp db export 是啞的
社群公認讓 agent 碰資料庫的安全儀式,是「動手前先 wp db export 備份」。我在 SQLite 站上實測了這道保險:
完整輸出只有這樣:
env: mysqldump: No such file or directory Warning: Failed to get current character set of the posts table.
因為 wp db export 是 shell out 去呼叫 mysqldump,而 SQLite 站上根本沒有 MySQL。
它失敗了,但訊息裡沒有 Error 字樣。任何用 grep -i error 判斷成敗的自動化腳本,都會認為備份成功。再把它跟第一個坑疊起來(pipe 吃掉 exit code),你就得到一個完美的災難配方:腳本回報備份成功、實際上沒有備份、然後放心去跑破壞性指令。
能用的替代方案是 wp export(WXR 格式),我實測可用。wp post、wp option 這些結構化指令也都正常,壞掉的只有需要原生 MySQL 的那些。可以直接抄的防禦是:備份後不要信任訊息文字,去驗檔案本身。
wp export --dir=./backups
[ -s ./backups/*.xml ] || { echo "備份失敗,中止"; exit 1; }20 項變 0 項:有沒有家規,差在這裡
前面都是環境問題。這段講程式碼。
我寫了一個約 50 行的公告外掛(後台可編輯、前台顯示、記錄瀏覽次數),刻意用「一句話 prompt 會產出的那種寫法」。然後用官方的 Plugin Check 跑分,不自己評:
wp plugin install plugin-check --activate wp plugin check moon-notice
結果 7 個 ERROR、13 個 WARNING,總共 20 項。而且完全命中社群公認的四大盲點:
最後那個不是理論問題,是真的可以被利用的 SQL injection:
$page = $_SERVER['REQUEST_URI'];
$wpdb->query("INSERT INTO {$wpdb->prefix}moon_views (page) VALUES ('$page')");網址列就是輸入點。另外還有兩個不寫就一定中的低級錯:缺 License 標頭、缺 if ( ! defined( 'ABSPATH' ) ) exit;。
然後我依照 WordPress 安全規範重寫同一個外掛,再跑一次:
Plugin Check 對照結果
裸奔版:7 ERROR + 13 WARNING = 20 項
有家規版:2 ERROR + 0 WARNING = 2 項
剩下那 2 項是 readme_*_non_official_language,只因為我 readme 寫中文,跟程式安全無關。安全問題從 20 項降到 0 項。
差別不在模型聰不聰明,在於有沒有人告訴它 WordPress 的規矩。所以把規矩寫下來的那 20 分鐘投資,第一次 session 就回本。
護欄三件套,以及我自己寫錯的那一版
標準架構是三層:wp-cli.yml 管連線、CLAUDE.md 寫家規、.claude/settings.json 設 allow/deny。但 deny 清單有個限制:遇到 --dangerously-skip-permissions 就破功。唯一硬擋得住的是 PreToolUse hook(其他好用的Claude Code 指令與設定我另外寫過)。
所以我寫了一支 wp-guard.sh,擋這些:資料庫刪除重置、原生 SQL、沒加 --dry-run 的 search-replace、指向 @prod、讀取 wp-config.php、一次更新全部外掛。寫完測試,結果:
🛑 擋下 | wp db drop --yes ✅ 放行 | wp db query "DELETE FROM wp_posts" ← 這行不該過
追下去發現,我的 hook 是這樣取指令的:
cmd="$(printf '%s' "$payload" | jq -r '.tool_input.command // empty')" [ -z "$cmd" ] && exit 0 # ← 問題在這
jq 解析失敗時 cmd 是空的,然後 exit 0 直接放行。
fail-open 的護欄,比沒有護欄更危險,因為你以為自己被保護著。
修成 fail-closed(解析失敗改掃原始 payload、payload 空就直接擋)之後重測,7 個危險指令全擋、3 個唯讀指令全放行,連「畸形 JSON 裡藏著 wp db query」都攔得下來。這種東西照文件抄一輩子都遇不到,只有真的動手寫、真的去測才會撞見。
我的想法 — 九黎月怎麼看這件事
做完這輪我一直想到一個詞:入門。
戲班收徒不是先教唱,是先掃地、先站樁、先學規矩。外行人覺得那是折騰,學了兩年還沒上台。可是規矩不是拿來限制你的,是替你擋掉那些你還看不見的坑。等你真的站上台,那些沒學規矩的人正在台上手忙腳亂。
AI 寫 WordPress 現在就是這樣。它能在兩小時裡生出一個能跑的外掛,那是它的天分,快得嚇人。但 20 項違規裡有一個真的 SQL injection,而它自己不知道。Patchstack 的 2026 報告說 2025 年 WordPress 生態新增 11,334 個漏洞,年增四成二,九成一出在外掛,而且點名了 vibe coding。有人 48 小時做出多語外掛,上線當天炸三個 bug;有人兩三天寫完,花了七週才過官方審查。
快的是「能跑」,不是「能上線」。這兩件事之間的距離,就是規矩。
所以護欄不是綁住 AI 的繩子,是給它的戲班規矩。你把家規寫進 CLAUDE.md、把紅線寫進 hook,它就從一個很有天分但沒師父的新人,變成一個知道哪裡不能踩的角兒。
順帶一提,那個 fail-open 的漏洞是我自己寫的。連寫護欄的人都會寫錯護欄,所以護欄本身也要測。
結論:讓 WP-CLI 交給 Claude Code 之前,先做這六件事
做完這六件事,AI 寫 WordPress 就從賭博變成工程。
全文數據為 2026-07-28 本機實測:macOS、PHP 8.5.8、WP-CLI 2.12.0、WordPress 7.0.2 + SQLite、Node v22.18.0。外部數據來源:WP-CLI 官方 handbook、WordPress Playground 官方文件、Patchstack《State of WordPress Security in 2026》。