背景
VSCodeでMarkdownを書いてgit pushするだけでWordPressに自動投稿する仕組みを、GitHub Actionsで組もうとしたところ、403 Forbiddenで長時間ハマりました。原因究明の過程を記録します。
症状の整理
ローカルではnpm run publishが完璧に動いていたのに、GitHub Actions経由だけ失敗しました。
| テスト方法 | 結果 |
|---|---|
ローカル(npm run publish) |
✅ 成功 |
| ブラウザ(GET) | ✅ 成功 |
| curl(POST) | ✅ 成功 |
| GitHub Actions | ❌ 403エラー |
同じAPIエンドポイント・同じ認証情報なのに、実行環境によって結果が変わるのが不可解でした。
切り分け1: WAFを疑う → 違った
XSERVERのWAFがREST APIをブロックしている可能性を最初に疑いましたが、確認するとWAFはすべてOFF。原因ではありませんでした。
切り分け2: REST API自体・Application Passwordを疑う → どちらも正常
curl -X POST "https://example.com/wp-json/wp/v2/posts" \
-u "user:Application Password" \
-H "Content-Type: application/json" \
-d '{"title":"Curl Test","content":"Test","status":"draft"}'
curlでのPOSTは成功。Application Passwordにも問題なし。ここまでで「APIも認証も生きているのに、GitHub Actionsからだけ拒否される」という奇妙な状況が確定しました。
ブレイクスルー:エラーログを詳細化する
} catch (error) {
if (error.response?.status === 403) {
console.error('❌ 投稿エラー: 403 Forbidden');
console.error('💡 XSERVERのセキュリティ設定を確認してください');
}
}
このメッセージをヒントに、サーバーパネルを改めて確認しました。
真の原因:国外IPアクセス制限
XSERVERの「WordPressセキュリティ設定」内に、WAFとは別に**国外IPアクセス制限(REST APIアクセス制限)**という設定がありました。
GitHub Actions(アメリカのサーバーで実行)
↓ 国外IPからアクセス
XSERVERの国外IPアクセス制限
↓ ブロック
403 Forbidden
ローカルは日本国内のIPだったので通過し、GitHub Actions(Ubuntu runnerは主にアメリカ)は国外IPとしてブロックされていた、というのが全貌でした。
対処
サーバーパネル → セキュリティ → WordPressセキュリティ設定
→ 対象サイト → 国外IPアクセス制限設定
→ REST APIアクセス制限: OFF
設定反映を数分待ってから再実行すると成功しました。
セキュリティ上の懸念について
「REST APIの国外アクセスを許可して大丈夫か」という点は、WordPress REST APIが読み取り(GET)と書き込み(POST/PUT/DELETE)で保護レベルが違うことを理解すれば整理できます。
| レベル | 対象 | 保護 |
|---|---|---|
| 読み取り | GET(記事一覧取得など) | 誰でもアクセス可(公開情報のため問題なし) |
| 書き込み | POST/PUT/DELETE | Application Password必須(漏れない限り安全) |
トラブルシューティングチェックリスト
WordPress REST APIで403に遭遇したら、上から順に確認すると早いです。
- XSERVERの国外IPアクセス制限(REST APIアクセス制限)
- WAF設定(
/wp-json/を除外しているか) - Application Passwordの有効性
-
curlでのPOSTテストで問題を切り分け
まとめ
「ローカルは成功、CI環境だけ失敗」という症状は、実行環境のIPアドレスの違いを疑うのが定石だと学びました。WAF設定・Application Password作成手順まで含めた全体の流れはこちらにまとめています。