WP Activity Log v5.6.4でアプリパスワード削除時に500エラーが出る原因と回避策

WP Activity Log v5.6.4でアプリパスワード削除時に500エラーが出る原因と回避策

WP Activity Log v5.6.4でアプリパスワード削除時に500エラーが出る原因と回避策

WP Activity Log v5.6.4を有効化したWordPressサイトで、プロフィール画面からアプリケーションパスワードを取り消すと「このサイトで重大なエラーが発生しました」と表示される場合、プラグインのアップデート待ちでは解決しない。原因はWP Activity Logが汎用のupdate_user_metaフックに対するメタキーの検証を怠っている点にあり、PHP 8ではcount()に文字列を渡すとTypeErrorが発生して致命的エラーになる。この記事では、エラーの仕組みから、手動での回避策、上位互換のためのコードパッチまでを具体的に示す。

エラーの全容と発火する条件

エラーの全容と発火する条件

WP Activity Log v5.6.4に収録されたWP_User_Profile_Sensor::event_application_password_added()は、汎用のupdate_user_metaアクションにフックされている。関数シグネチャには$meta_keyが渡されているが、コールバック内でこれを一度も検証しない。代わりにHTTPリファラとREQUEST_URIだけを見て、アプリケーションパスワード変更のリクエストかどうかを判定している。

このため、ユーザーのプロフィール画面からアプリケーションパスワードを取り消すときに、REST APIへのDELETEリクエストが発行される。リファラチェックはプロフィールページを指し、URIチェックも/wp/v2/users/{id}/application-passwords/...を含むため、両方の条件を通過する。ここでBuddyBoss Appのようなプラグインが、同じリクエストのディスパッチ中にlast_activityというユーザーメタを更新すると、本来アプリケーションパスワードのメタを想定していたセンサーが誤ってそのtimestamp文字列を処理してしまう。

致命的エラーの発生箇所とスタックトレース

致命的エラーの発生箇所とスタックトレース

実運用のログには、次のような未捕捉のTypeErrorが記録される。PHP 8ではcount()の引数が配列またはCountableでない場合、警告ではなくTypeErrorがスローされる。WP Activity Logのコードは文字列をcount()に渡しているため、リクエストが500エラーになる。

エラーの発火経路
1. プロフィール画面で操作 アプリパスワードの取り消しをクリックする
2. REST APIリクエスト発行 DELETE /wp/v2/users/{id}/application-passwords/{uuid}
3. 別プラグインがメタを更新 BuddyBoss App が last_activity のtimestamp文字列を書き込む
4. センサーが誤発火 アプリパスワードと無関係なメタ書き込みでもコールバックが動く
5. count()が文字列を受けてTypeError 500エラーになり、操作が完了しない
PHP 8のTypeErrorを引き起こす誤発火  無関係なメタ更新

スタックトレースを追うと、クラスの203行目でcount( $_meta_value )が呼ばれている。ここで$_meta_valueはtimestampの文字列であり、$old_value_application_passwordsの配列である。文字列をcount()に渡すとPHP 8ではTypeErrorが発生し、アプリケーションパスワードの取り消しは実行されないまま処理が失敗する。

第一の対処方法、プラグインの停止で被害を止める

第一の対処方法、プラグインの停止で被害を止める

まず、サイトが利用者から見て壊れている状態を早く解消するには、WP Activity Logを停止する。管理画面にアクセスできる場合は「プラグイン」画面からWP Activity Logを無効化する。アクセスできない場合はFTPでwp-security-audit-logディレクトリをリネームする。リネームするとWordPressがプラグインを検出できなくなり、自動的に無効化される。

第二の対処方法、一時的にPHPのエラー表示を止める

第二の対処方法、一時的にPHPのエラー表示を止める

WP Activity Logを使い続けたい場合は、PHPのcount()エラーが致命的にならないよう回避策を施す。だが、これは根本解決ではなく症状を隠すだけだ。むしろ、エラー自体を修正するパッチを適用する方が安全である。ただし、プラグインのアップデートで上書きされることを理解した上で、運用上の措置として行うかどうかを判断してよい。

ソースコードを直接修正する根本対応

ソースコードを直接修正する根本対応

WP Activity Logの該当ファイルはwp-security-audit-log/classes/WPSensors/class-wp-user-profile-sensor.phpである。コールバックの先頭で、メタキーが_application_passwordsでない場合は早期returnするようガードを追加する。これが今回のエラーを確実に止める最小の修正だ。

public static function event_application_password_added( $meta_id, $user_id, $meta_key, $_meta_value ) {
    if ( '_application_passwords' !== $meta_key ) {
        return;
    }
    // 以下、既存の処理
}

加えて、防御的措置としてcount()に渡す前に配列キャストを行うと、将来何らかの形で配列以外の値が混入した場合にも致命的エラーを防げる。メタキーガードだけでも今回の症状は解消するが、運用中のサイトでは両方の修正を施しておく方が堅牢だ。

} elseif ( count( (array) $_meta_value ) < count( (array) $old_value ) ) {

修正後、コード上の同じパターンが他に残っていないか、deleted_user_metaadded_user_metaへの登録も確認するとよい。同じクラス内で複数のフックが同様のリファラ+URIチェックだけに頼っている場合、似た条件のリクエストで誤発火する可能性がある。

PHP 8環境で注意すべきcount()の挙動

PHP 7.xでは、count()に文字列を渡しても警告が出るだけで処理は継続されていた。しかしPHP 8ではTypeErrorとしてスローされるため、これまで表面化しなかったコードの前提ミスが致命的エラーとして現れる。WP Activity Logに限らず、WordPressプラグインの旧コードでは、更新順にこうした潜在バグが発覚することがある。

サイトをPHP 8系へ更新した直後に、特定の操作でのみ500エラーが出る場合は、エラーログにcount(): Argument #1 ($value) must be of type Countable|array, string givenのような記録が残っていないか確認する。該当する場合は、エラーを起こしているプラグインのコードが文字列をcount()に渡している可能性が高い。

PHP 7.x
  • count()に文字列を渡すと警告のみ
  • 処理は継続される
  • 潜在的バグが表面化しない
PHP 8.x
  • TypeErrorがスローされる
  • 致命的エラーで500応答
  • 操作が完了しない
緩やかなエラー  致命的エラー

よくある質問

WP Activity Logを無効化すると監査ログは消えますか?

無効化しても記録済みの監査ログはデータベースに残る。ただし、無効化している間に発生したイベントは記録されない。復旧後にプラグインを再度有効化すれば、既存のログを閲覧できる。

BuddyBoss Appが原因なのでBuddyBoss側を停止すれば直りますか?

BuddyBoss Appがユーザーメタを更新するタイミングが発火に重なっているが、根本的な誤動作はWP Activity Log側のフック設計にある。BuddyBoss Appが動いていなくても、別のプラグインが同様にRESTリクエスト中にユーザーメタを更新すれば同じエラーが起きる。

WP Activity Logのバージョンを下げれば回避できますか?

過去のバージョンが同じコードを含んでいる場合、単純なダウングレードでは解消しない。今回のクラスのコールバックを変更せずに添付された報告では、v5.6.5にも修正が含まれていないと指摘されている。信頼できる最新の修正が入るまでは、上記のコードパッチを適用するか、プラグインを停止する方が確実だ。

プロフィール画面でアプリパスワードを管理できる権限がないユーザーも影響を受けますか?

このエラーはアプリケーションパスワード管理を行えるユーザーに限らず、同じリクエスト経路でユーザーメタが更新される状況であれば発火しうる。ただ、発火条件としてプロフィール画面からの操作と、REST APIのURIにアプリケーションパスワードのパターンが含まれることが必要になる。

プラグインをアップデートしたら勝手に直りますか?

プラグインの開発者がメタキーガードを実装したバージョンをリリースすれば直る。ただし、現時点で修正が含まれているかはリリースノートとソースを確認する必要がある。修正が見つからないうちは、手動パッチか無効化で運用を守る。

この記事のポイント

  • WP Activity Log v5.6.4の500エラーはPHP 8のcount()エラーが原因
  • コールバックがメタキーを検証せず、アプリパスワードと無関係なユーザーメタで誤発火する
  • メタキーガードを追加するコードパッチが根本解決になる
  • 配列キャストを加えるとPHP 8の厳格なエラーに強いコードになる
  • 修正版が出るまでは、プラグイン停止かパッチ適用で被害を防ぐ
佐々木 太陽

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化 ・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門 ・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標 ・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意 ・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

メッセージを残す