Skip to content

WordPress: デプロイ前にサーバ側のコアバージョンを照合して巻き戻りを防ぐ - #4

Merged
naokazuterada merged 1 commit into
mainfrom
feature/wp-core-version-check
Jul 27, 2026
Merged

WordPress: デプロイ前にサーバ側のコアバージョンを照合して巻き戻りを防ぐ#4
naokazuterada merged 1 commit into
mainfrom
feature/wp-core-version-check

Conversation

@naokazuterada

Copy link
Copy Markdown
Member

背景

danc.kyushu-u.ac.jp が wp2shell(CVE-2026-63030) による攻撃を受け、不正な管理者アカウントを18個作られた。

調査と対応の記録: https://github.com/karappo/danc.kyushu-u.ac.jp/issues/18

直接の要因は wp-config.phpAUTOMATIC_UPDATER_DISABLED で自動更新を止めていたこと。WordPress は 2026-07-17 に緊急リリースと強制自動更新を世界配信したが、この設定のため受け取れず、脆弱なバージョンのまま放置されて攻撃を受けた。

ただしこの設定自体には理由がある。WP コアを git 管理して mirror(--delete 付き)で配信する構成では、サーバ側で自動更新が入るとデプロイのたびに古いコアへ巻き戻る。巻き戻り=セキュリティ修正の消失なので、うかつに自動更新を有効にできなかった。

このPRで巻き戻りを機械的に防げるようにし、自動更新を有効にしたまま運用できる状態を作る。

変更内容

before_sync の冒頭(メンテ画面を出す)で、サーバ側の wp-includes/version.php を取得してリポジトリ側と照合する。

状態 挙動
サーバの方が新しい 中断(サーバ側で自動更新が入った)
リポジトリの方が新しい 通す(これから更新を配信する正常なデプロイ)
同じ 通す
サーバに WP が無い / 取得失敗 通す(初回デプロイ等)
リポジトリに WP コアが無い 何もしない(テーマのみのリポジトリ等)

中断時の出力:

[DEPLOY] ==================================================================
[DEPLOY]  デプロイを中断しました
[DEPLOY]  サーバ側の WordPress の方が新しいため、このまま配信すると巻き戻ります
[DEPLOY]
[DEPLOY]    サーバ側   : 7.0.2
[DEPLOY]    リポジトリ : 7.0.1
[DEPLOY]
[DEPLOY]  サーバ側で WordPress の自動更新が実行されています。
[DEPLOY]  このまま同期するとコアが 7.0.1 に戻り、7.0.2 で入った
[DEPLOY]  セキュリティ修正が失われます。
[DEPLOY]
[DEPLOY]  手元で下記を実行し、コミットして push し直してください。
[DEPLOY]
[DEPLOY]    wp core update --version=7.0.2 --force
[DEPLOY] ==================================================================

サーバ側のバージョンを明記しているので、そのままコピーして手元で更新できる。

実装上のポイント

  • 中断は exit 1deploy.shbefore_sync の戻り値を見ていない(before_sync を呼ぶだけ)ため、return 1 では止まらない。deploy.sh は無改修で済ませている
  • メンテ ON より前に呼ぶ。中断時にメンテナンス画面を残さないため
  • バージョン比較は sort -V。文字列比較だと 6.9.10 < 6.9.9 と誤判定するため
  • リモートのファイル取得は cat のみ。パース処理はローカルで行い、SSH/FTP に渡すコマンドを単純に保っている(rsync/lftp 両対応)
  • 緊急避難用に DEP_WP_SKIP_VERSION_CHECK=1 を用意

影響範囲

.depinc.sh は各サイトのリポジトリではなく raw URL からデプロイのたびにダウンロードされるため、マージ時点で全 WordPress サイトに反映される。

影響は安全側に倒れる。

  • 自動更新が無効なサイト → サーバ側は更新されないので中断しない(従来通り)
  • 既にサーバとリポジトリが乖離しているサイト → 次のデプロイで中断する。巻き戻し事故が起きる寸前の状態なので、止まるのが正しい挙動

各サイトでの設定(このPRとは別作業)

このPRを入れたうえで、各サイトの wp-config.php を以下に変更すると、セキュリティ修正が自動で当たるようになる。

// 変更前
define('AUTOMATIC_UPDATER_DISABLED', true);

// 変更後(コアのマイナーリリースのみ自動更新)
define('WP_AUTO_UPDATE_CORE', 'minor');

順序に注意: 必ずこのPRを先にマージすること。逆にすると、自動更新が有効なのに検知の仕組みが無い期間が生まれる。

なお AUTOMATIC_UPDATER_DISABLED を外すと翻訳ファイルの自動更新だけはデフォルトで有効になる。wp-content/languages を git 管理している場合は次のデプロイで巻き戻るが、version.php は変わらないので中断はされず、実害は翻訳がわずかに古くなる程度。気になる場合は add_filter('auto_update_translation', '__return_false'); で止められる。

動作確認

  • bash -n で構文チェック済み
  • バージョン比較ロジックを個別に検証済み(7.0.1 vs 7.0.2 → 中断、6.9.10 vs 6.9.9 → 通す、など)
  • version.php からのバージョン抽出を実ファイルで確認済み
  • マージ後、danc.kyushu-u.ac.jp のデプロイで実走を確認する(同バージョン同士で通過することの確認)

WP コアを git 管理して mirror --delete で配信する構成では、サーバ側で自動更新が
入るとデプロイのたびにコアが古いバージョンへ巻き戻り、セキュリティ修正が失われる。
そのため自動更新を有効にできず、緊急のセキュリティリリースを取りこぼす問題があった。

before_sync の冒頭でサーバ側の version.php を読んで照合し、サーバの方が新しければ
両方のバージョンを明示して中断する。これにより wp-config.php で WP_AUTO_UPDATE_CORE
を有効にしたまま運用できる。

deploy.sh は before_sync の戻り値を見ないため、中断は exit で行っている。

背景: karappo/danc.kyushu-u.ac.jp#18

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant