タグアーカイブ WordPress

CCBillプラグイン1.3.2更新で重大なエラーが出た時の対処法

CCBillプラグイン1.3.2更新で重大なエラーが出た時の対処法

CCBillプラグインを1.3.2へ更新した直後にサイトが落ちた場合、原因は更新版に必須のincludes/GelatoConfig.phpが同梱されていないことだ。対処は1.3.1へロールバックするのが確実で、require_once行の削除や空ファイルの作成では正常に戻らない。

なぜプラグイン更新後にサイトが落ちるのか

なぜプラグイン更新後にサイトが落ちるのか

プラグインのメインファイルは読み込み時にrequire_once ‘includes/GelatoConfig.php’;という命令を実行する。ところが1.3.2の配布ZIPにはincludesディレクトリに該当ファイルが含まれていない。PHPは必要なファイルを開けないため、その場で処理を中断し、WordPressは「このサイトで重大なエラーが発生しました」という画面に切り替わる。

更新後 1.3.2 require_once で includes/GelatoConfig.php を読み込む
エラー ファイルが存在しないため「このサイトで重大なエラーが発生しました」と表示される
対処後 1.3.1 必要なファイルが揃っている旧版に戻して正常動作

このデモは、更新版で必須ファイルが欠落した際にエラーが発生し、旧版で解消する流れを表している。

読み込み失敗が致命的エラーへ進む流れ

require_onceは指定したファイルを必ず読み込む命令であり、見つからなければPHPの実行が止まる。WordPressはこの致命的エラーを検知して、訪問者には復旧用の画面を表示し、管理者には状況を伝えるメールを送ることがある。サイトが突然止まった場合は、まず更新直後に起きたことを前提に動くと早期に原因へたどり着ける。

他のファイルも同じクラスに依存している

1.3.2の他の複数ファイルはGelatoConfigクラスのメソッドやプロパティを呼び出している。そのため、require_once行をコメントアウトしたり、中身のないincludes/GelatoConfig.phpを作ったりしても、次の段階でクラスが見つからないエラーへ変わるだけだ。今回の不具合は行の書き換えで吸収できる規模ではない。

エラーログで原因を確定させる手順

エラーログで原因を確定させる手順

画面が真っ白になったり、重大なエラーの表示だけでは原因が見えない。まずはWordPressのデバッグログを有効にして、どのファイルで止まっているかを確認する。

wp-config.phpでデバッグログを有効にする

FTP・SFTPでサーバーに接続し、WordPressのルートにあるwp-config.phpを編集する。以下の定数を設定すると、エラー内容がwp-content/debug.logに記録される。

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

debug.logに記録された該当行を確認する

debug.logを開くと、require_once()がincludes/GelatoConfig.phpを開けなかったことや、GelatoConfigクラスが見つからない趣旨のエラー(英語表示では ‘Class GelatoConfig not found’)が記録されている。このログが取れたら、原因はプラグインのファイル欠落であると確定できる。

旧バージョンへ戻す具体的な手順

旧バージョンへ戻す具体的な手順

管理画面にアクセスできるかどうかで手順が変わる。ここでは先に全体フローを確認し、それぞれの詳細を説明する。

STEP 1 配布ページから1.3.1のZIPをダウンロードする
STEP 2 FTP・SFTPで wp-content/plugins/ へ接続する
STEP 3 既存プラグインフォルダを旧版で上書きする
STEP 4 キャッシュを削除し、サイトと管理画面を確認する

ロールバックの基本手順を示した。それぞれの詳細は次項で解説する。

公式配布ページから1.3.1のZIPを入手する

WordPress.orgのプラグインページを開き、下部にある詳細表示(Advanced View)から過去の版を選べる。画面下部のバージョン選択で1.3.1を指定し、ZIPをダウンロードする。ローカルに展開して、includes/GelatoConfig.phpが含まれていることをこの段階で確認しておくと安心だ。

FTP・SFTPでプラグインフォルダを置き換える

FTP・SFTPクライアントでサーバーに接続し、wp-content/plugins/ の該当プラグインフォルダを開く。既存のフォルダをいったん別名にリネームして退避し、展開した1.3.1のフォルダをアップロードする。リネーム後に新しいフォルダを置くと、サイト上では1.3.1が読み込まれる。

管理画面に入れないときの一時的な復旧

サイト全体が落ちて管理画面にも入れない場合は、FTP・SFTPで該当プラグインのフォルダをリネームして無効化する。これでサイトが表示されるようになれば、管理画面にログインして旧版ZIPをアップロードできる。自動更新が走る環境では、復旧前に更新を止めておくのが確実だ。

キャッシュを削除して反映を確認する

旧版への置き換え後は、サイトのキャッシュプラグインとブラウザのキャッシュを削除する。サーバー側キャッシュを使っている場合はそれもクリアする。その後、フロントと管理画面の両方が表示され、プラグイン設定が1.3.1に戻っていることを確認する。

require_once行の削除や空ファイルでは直らない理由

require_once行の削除や空ファイルでは直らない理由
誤った対処 行の削除 → クラスが見つからず別のエラーが発生する
誤った対処 空ファイルの作成 → 同じくクラス未定義で停止する
正しい対処 旧版1.3.1へ戻す → 欠落ファイルが揃い正常動作

部分的なコード修正では別のエラーへ移るだけで、旧版への切り戻しが最短の解決になる。

GelatoConfigクラスは複数のファイルから参照されている

1.3.2のコードはGelatoConfigクラスに依存する構造になっている。require_once行を消すとファイル読み込みは通っても、その後でクラスのプロパティやメソッドを呼ぶ箇所がエラーになる。空ファイルを作ってもクラス定義がないため、PHPは同じ理由で停止する。問題の本質は設定ファイルの有無ではなく、配布物からクラス定義ごと抜け落ちている点にある。

誤った修正をした場合のリスク

プラグイン本体を直接書き換えると、将来の更新で上書きされ、変更が失われる。また、クラス定義を部分的に再現できたとしても、決済処理など他の機能に影響が出るおそれがある。商用サイトでは旧版へ戻す方法が最も安全だ。開発元が修正版を配信するまでは、1.3.1に留めて更新を保留する。

再発を防ぐために更新前に確認したいこと

再発を防ぐために更新前に確認したいこと

ステージング環境で先に更新を試す

本番サイトへそのまま更新を適用せず、コピー環境(ステージング)でプラグイン更新を実行する。更新後にフロントと管理画面、主要な導線を一通り確認し、エラーがないことを確かめてから本番へ反映する。ステージング環境が用意できない場合は、更新前にフルバックアップを取っておく。

更新前に旧版のZIPを確保しておく

プラグインは自動更新で最新版だけが残り、旧版の入手経路が分からなくなることがある。今回のように最新版が壊れているケースでは、更新前に利用中のバージョンのZIPをダウンロードして保管しておくと速やかに戻せる。プラグインページの詳細表示からダウンロードできる。

更新直後に異常を検知したらすぐに切り戻す

サイトを更新した直後は、必ずトップページと管理画面、問い合わせフォームなど主要機能を開いて確認する。重大なエラーが出た場合は、原因調査より先に旧版へ戻すのが先決だ。ログの確認はその後で行い、開発元の修正版が出るまで更新を保留する。

よくある質問

プラグインを1.3.2に更新したのに管理画面に入れません。どうすればいいですか

FTP・SFTPでwp-content/plugins/ の中にある該当プラグインのフォルダをリネームして無効化する。これで管理画面に入れるようになったら、旧版1.3.1のZIPをアップロードして再び有効化する。

旧版の1.3.1はどこでダウンロードできますか

WordPress.orgのプラグインページにある詳細表示(Advanced View)から過去の版を選んでダウンロードできる。今回のような更新直後の不具合に備え、普段から利用中のバージョンのZIPを手元に保管しておくのが有効だ。

require_once行を削除してもサイトは戻らないのでしょうか

戻らない。削除すると次の段階でGelatoConfigクラスが見つからないエラーに変わる。空のファイルを置いてもクラス定義がないため解消しない。旧版へ戻すのが最短の対処だ。

プラグイン1.3.2に自動更新されないようにするには

該当プラグインの自動更新をオフにするか、サイト全体の自動更新設定でプラグイン更新を手動に切り替える。ただし修正版が公開された場合は、手動で更新を適用する必要がある。

サイトが重大なエラー画面のままの場合は、メールは届きますか

WordPressがサイト管理者へ復旧用リンク付きのメールを送ることが多い。メールが届かない場合は、FTP・SFTPでプラグインを無効化して管理画面への導線を確保する。

この記事のポイント

  • 1.3.2では必須ファイルincludes/GelatoConfig.phpが欠落している
  • 行の削除や空ファイルではエラーの種類が変わるだけで直らない
  • 旧版1.3.1へ戻すのが最短の対処だ
  • 旧版ZIPはプラグインページの詳細表示から入手できる
  • 更新前にはバックアップと旧版の確保、ステージングでの確認を行っておく
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の厳格なエラーに強いコードになる
  • 修正版が出るまでは、プラグイン停止かパッチ適用で被害を防ぐ
WordPressに勝手にインストールされるwp-flareマルウェアの感染経路と駆除方法

WordPressに勝手にインストールされるwp-flareマルウェアの感染経路と駆除方法

WordPressに「wp-flare」という身に覚えのないプラグインがインストールされていた場合、それはマルウェアによる不正侵入の痕跡だ。感染したプラグインファイルとデータベース上の登録を削除し、侵入経路を特定して塞ぐことが根本対策になる。

wp-flareマルウェアの感染経路はどこにあるのか

wp-flareマルウェアの感染経路はどこにあるのか

wp-flareは正規のプラグインディレクトリには存在しない、攻撃者が設置する不正なプラグインだ。このプラグインがインストールされるということは、すでに何らかの方法でサイトの管理者権限を奪われている、またはファイルを書き込む経路を確保されていることを意味する。

感染経路として最も多いのは、使用しているプラグインやテーマに存在する脆弱性の悪用だ。すべてのプラグインが最新版でも、サポートが終了した古いプラグインや、公式ディレクトリにない野良プラグインに脆弱性が残っているケースがある。攻撃者はこうした穴を突いて任意のファイルをアップロードし、不正なプラグインを設置する。

次に疑うべきは、管理者パスワードの漏洩や総当たり攻撃の成功だ。二段階認証(2FA)を導入していても、XML-RPC経由の認証試行や、別サイトから流出した同じパスワードを使い回している場合は突破されることがある。

複数サイトが同時期に感染する理由

異なるホスティングの複数サイトが同時期に感染する場合、共通して使っているプラグインやテーマ、管理ツールが感染源になっている可能性が高い。たとえば、同じ開発元が配布するプラグインの配布元が改ざんされていたり、管理用のパソコン自体がマルウェアに感染してFTPやSSHの認証情報を窃取されているケースもある。

感染経路の特定には、各サイトのファイル更新日時とアクセスログを突き合わせるのが有効だ。wp-flareのファイルが設置された日時を調べ、その前後に不審なPOSTリクエストやログイン試行がないかを確認する。

感染経路の候補
プラグインの脆弱性 任意ファイルのアップロード wp-flare設置
パスワード漏洩 管理者ログイン突破 プラグインインストール
FTP・SSH認証情報の窃取 ファイル直接改ざん wp-flare設置
侵入の入口  攻撃者の行動  最終的な被害

上の図は感染に至る典型的な3つの経路を示している。どの経路であっても最終的にはwp-flareという不正プラグインが設置される点が共通している。

感染したサイトで最初に確認すべき症状

感染したサイトで最初に確認すべき症状

wp-flareに感染したサイトでは、管理画面のプラグイン一覧に「wp-flare」という名前の見慣れない項目が表示される。ただし攻撃者がプラグインの表示名を偽装している場合もあるため、一覧に表示されないこともある。

そのほか、以下のような症状が現れることがある。すべてに該当する必要はなく、1つでも当てはまれば感染を疑うべきだ。

  • サイトが知らないURLにリダイレクトされる
  • 検索結果に表示されるタイトルや説明文が書き換えられている
  • 管理画面の動作が急に重くなった
  • 見覚えのない管理者ユーザーが追加されている
  • サーバーに身に覚えのないファイルが増えている

最も確実なのは、サーバーのプラグインディレクトリ(wp-content/plugins/)を直接確認することだ。wp-flareという名前のフォルダが存在する場合は、マルウェア感染と断定してよい。

wp-flareマルウェアを駆除する手順

wp-flareマルウェアを駆除する手順

wp-flareの駆除は、プラグインファイルの削除だけでなく、データベース上の不正な登録や、設置されたバックドアの除去まで行う必要がある。以下の手順で進める。

STEP 1 サイト全体のバックアップを取得する
STEP 2 wp-flareプラグインのフォルダを削除する
STEP 3 データベースから不正な登録を削除する
STEP 4 全ファイルをスキャンしてバックドアを除去する
STEP 5 全パスワードと認証情報を変更する

この手順は上から順に実施する。途中でサイトが表示できなくなっても復旧できるよう、STEP 1のバックアップは必ず最初に行う。

wp-flareのプラグインフォルダを削除する

FTPソフトまたはホスティングのファイルマネージャーにログインし、wp-content/plugins/wp-flare ディレクトリを丸ごと削除する。管理画面からプラグインを「削除」しようとしても、プラグイン自体が無効化を妨害する仕組みを持っている場合があるため、ファイルシステム上から直接削除するのが確実だ。

削除後、管理画面のプラグイン一覧に「wp-flare」が表示されなくなることを確認する。もしプラグイン一覧にまだ表示される場合は、データベース側に登録が残っている可能性が高い。

データベースから不正な登録を削除する

WordPressのプラグイン情報は、データベースの wp_options テーブルにある active_plugins という項目で管理されている。不正プラグインがここに登録されていると、ファイルを削除しても管理画面に残り続ける。

phpMyAdminなどのデータベース管理ツールで wp_options テーブルを開き、option_nameactive_plugins の行を探す。その値の中に wp-flarewp_flare を含む文字列があれば、その部分を削除する。操作前にデータベースのバックアップを取得しておくこと。

バックドアの痕跡を全ファイルから探す

wp-flare本体を削除しても、攻撃者が別の場所にバックドア(再侵入用の隠しファイル)を設置している場合がある。主に以下の場所を確認する。

  • テーマディレクトリ内の見覚えのないPHPファイル
  • アップロードディレクトリ内のPHPファイル(画像のはずなのに拡張子がPHPになっているもの)
  • WordPress本体の wp-adminwp-includes 内の改ざんファイル
  • サイトのルート直下に置かれた小さなPHPファイル

ファイル数が多い場合は、サーバー上で find コマンドを使って直近に変更されたファイルを抽出すると効率的だ。感染が確認された日時以降に更新されているPHPファイルを重点的に調べる。

find /path/to/wordpress -name "*.php" -mtime -30

このコマンドは、指定したWordPressディレクトリの中で過去30日以内に更新されたPHPファイルを一覧表示する。感染が判明した時期に合わせて日数を調整する。

全パスワードと認証情報を変更する

駆除が完了したら、侵入経路に関係なく以下の認証情報をすべて変更する。感染中に窃取されていた可能性を考慮し、同じパスワードの使い回しは避ける。

  • WordPress管理画面の全ユーザーのパスワード
  • FTP・SSHの接続パスワード
  • データベースの接続パスワード
  • ホスティングのコントロールパネルのパスワード
  • メールアカウントのパスワード

再発を防ぐためのセキュリティ対策

再発を防ぐためのセキュリティ対策

wp-flareを駆除しても、感染経路を塞がなければ再び同じ被害に遭う。特に複数サイトが同時期に感染した場合は、サイト単体の対策だけでなく、管理環境全体の見直しが必要だ。

使用中のプラグインとテーマを棚卸しする

すべてのサイトで使用しているプラグインとテーマの一覧を作成し、以下に該当するものがないか確認する。これらが感染源になっている可能性が高い。

  • 配布元が公式ディレクトリではないプラグイン
  • 更新が1年以上停止しているプラグイン
  • サイトの機能上不要になったプラグイン
  • 正規の配布元ではないサイトから入手したテーマ

不要なプラグインは削除し、更新が停止しているプラグインは代替品への移行を検討する。どうしても使い続ける必要がある場合は、開発元のセキュリティ情報を定期的に確認する。

管理用パソコンのマルウェアスキャンを行う

複数のサイトが同時期に感染した場合、サイトではなく管理用のパソコンが感染源になっている可能性がある。FTPやSSHの接続情報を保存しているFTPソフトの設定ファイルから認証情報が窃取され、攻撃者に悪用されるケースがある。

管理用パソコンで信頼できるアンチウイルスソフトのフルスキャンを実施し、FTPソフトやパスワード管理ソフトの保存データが漏洩していないか確認する。スキャン後は、保存済みのパスワードもすべて変更するのが安全だ。

Before FTPソフトに平文で保存された認証情報が窃取される
After パスワードを変更し、FTPソフトの保存機能を使わない運用に切り替える

FTPソフトにパスワードを保存する機能は便利だが、マルウェア感染時には認証情報の流出経路になる。可能であれば、接続のたびにパスワードを入力する運用に切り替えるとリスクを減らせる。

ファイル変更の監視を導入する

感染の早期発見には、サーバー上のファイル変更を監視する仕組みが有効だ。WordPressのセキュリティプラグインには、ファイルの改ざんを検知して通知する機能を持つものがある。プラグインの新規インストールや、想定外のファイル変更があった場合にメールで知らせる設定にしておくと、被害が拡大する前に対処できる。

XML-RPCを無効化する

XML-RPCはWordPressの外部連携機能だが、総当たり攻撃やSSRF攻撃の入口として悪用されることが多い。外部サービスとの連携で使っていない場合は、無効化するのが効果的な対策になる。

セキュリティプラグインの多くにXML-RPCを無効化するオプションがある。もしくは、以下のコードをテーマの functions.php に追加する方法もある。

add_filter( 'xmlrpc_enabled', '__return_false' );

ただし、このコードは子テーマの functions.php に追加するのが基本だ。親テーマを直接編集すると、テーマ更新時にコードが消えるため注意する。

よくある質問

wp-flareは公式プラグインディレクトリに存在しないのか

存在しない。wp-flareはWordPress公式ディレクトリに登録されておらず、攻撃者が独自に設置する不正なプラグインだ。プラグイン一覧に表示される名前が同じでも、正規のプラグインと混同しないよう注意する。

管理画面からwp-flareを削除できない場合はどうするのか

管理画面からの削除ができない場合は、FTPまたはファイルマネージャーでサーバーに直接アクセスし、プラグインディレクトリからフォルダを削除する。削除後もプラグイン一覧に表示される場合は、データベースの active_plugins に残っている登録を手動で削除する必要がある。

感染したサイトのバックアップは復元に使えるのか

感染前のバックアップが確実に存在する場合は、バックアップからの復元が最も確実な駆除方法になる。ただし、バックアップ自体が感染後に取得されたものであれば復元しても意味がない。取得日時を必ず確認し、感染前のものを使う。

wp-flare対策に有効なセキュリティプラグインはあるのか

定期的なマルウェアスキャン、ファイル変更の監視、ログイン試行の制限、XML-RPCの無効化などを提供するセキュリティプラグインが有効だ。ただし、プラグインを導入するだけで完全に防げるわけではない。プラグインの棚卸しやパスワード管理など、運用面の対策と組み合わせることが重要になる。

同じパスワードを複数サイトで使い回してもよいのか

避けるべきだ。1つのサイトでパスワードが漏洩すると、同じパスワードを使うすべてのサイトが連鎖的に感染する原因になる。サイトごとに異なるパスワードを設定し、パスワード管理ソフトで一元管理するのが安全な運用だ。

この記事のポイント

  • wp-flareは攻撃者が設置する不正なプラグインだ
  • 感染経路はプラグインの脆弱性、パスワード漏洩、FTP認証情報の窃取が主な候補になる
  • 駆除はファイル削除とデータベースの掃除、バックドア除去まで行う
  • 複数サイトが感染した場合は管理用パソコンのマルウェアスキャンも必要だ
  • 再発防止にはプラグインの棚卸しとファイル変更の監視が有効だ
Tutor LMSでコース画像が小さくぼやける原因と画像サイズ変更の手順

Tutor LMSでコース画像が小さくぼやける原因と画像サイズ変更の手順

Tutor LMSのコース一覧でサムネイル画像が小さくぼやける症状は、プラグインが登録した専用画像サイズ(約370×235px)をテンプレートが呼び出し、ブラウザ側で大きな容器に引き伸ばしているのが主な原因だ。子テーマでテンプレートを上書きするか、フィルターフックで画像サイズを変更すれば解決する。

Tutor LMSでコース画像がぼやける仕組みと原因

Tutor LMSでコース画像がぼやける仕組みと原因

Tutor LMSはコース一覧ページを表示する際、専用の画像サイズを呼び出す。このサイズはプラグインがサーバー環境に登録したもので、コースカードのレイアウトに合わせて小さい寸法に設定されていることが多い。

問題は、テーマ側のスタイルシートがコースカードをより広い幅で表示しようとする場面だ。画像の実寸(約370×235px)に対して、実際の表示領域がそれを上回ると、ブラウザが画像を無理に拡大する。高解像度の元画像をアップロードしても、プラグインが生成した小さなサムネイルを参照している限り、ぼやけや文字の潰れは解消されない。

また、Tutor LMSのコースループ用テンプレートは標準の post_thumbnail_size フックを無視し、独自のサイズ指定を直接コード内に持っている。そのため、WordPressの標準設定から画像サイズを変更しても、コース一覧に反映されないという構造的な理由がある。

Before(症状)
元画像は高解像度(4K)でも
370×235pxのサムネイル生成 広い容器に引き伸ばし ぼやける・文字が読めない
After(修正後)
高解像度の画像サイズを直接参照
fullサイズ画像 表示領域に最適化 鮮明で読みやすい
症状の状態  修正後

このデモは、Tutor LMSが小さいサムネイルを呼び出してからブラウザが拡大する流れと、修正後に高解像度画像を直接参照する流れを示している。

テンプレート上書きで画像サイズを変更する手順

テンプレート上書きで画像サイズを変更する手順

最も確実な方法は、Tutor LMSのテンプレートファイルを子テーマにコピーし、画像サイズの指定を書き換えることだ。プラグイン本体のファイルを直接編集するとアップデートで上書きされるため、必ず子テーマを使う。

Tutor LMSのテンプレート構造を確認する

Tutor LMSのテンプレートは wp-content/plugins/tutor/templates/ ディレクトリ内に配置されている。コース一覧のカードを構成するテンプレートは、templates/course/loop/ または templates/loop/ 以下のファイル群だ。バージョンによって多少の違いはあるが、コースカードの表示を担当するファイルにサムネイル呼び出しが含まれている。

管理画面の「プラグイン」→「プラグインファイルエディター」からTutor LMSを選択し、templates/ フォルダを展開すると実ファイル名を確認できる。FTPで接続できるなら wp-content/plugins/tutor/templates/ を直接参照する方が速い。

子テーマにテンプレートをコピーする

対象のテンプレートファイルを子テーマ内の tutor/ ディレクトリにコピーする。Tutor LMSは子テーマの tutor/ フォルダを優先的に読み込む仕組みを持っている。コピー先のパスは wp-content/themes/子テーマ名/tutor/ だ。ディレクトリ構造を保ったままコピーする。

画像サイズの指定を変更する

コピーしたテンプレートファイル内の get_the_post_thumbnail() または tutor_course_loop_thumbnail() の呼び出し部分を探す。第二引数に指定されているサイズ名(例 'tutor-course-thumbnail')を 'full' または 'large' に変更する。

// 変更前
get_the_post_thumbnail($course_id, 'tutor-course-thumbnail');

// 変更後
get_the_post_thumbnail($course_id, 'full');

テンプレート内に the_post_thumbnail() が直接記述されている場合は、同じくサイズ引数を 'full' に置き換える。

STEP 1 templates/loop/ 内のコースカード用ファイルを特定する
STEP 2 子テーマの tutor/ ディレクトリに同一構造でコピーする
STEP 3 画像サイズの引数を full または large に変更する
STEP 4 キャッシュを削除し、コース一覧の表示を確認する

このデモは、テンプレート上書きの4つの手順を順番に示している。

フィルターフックで画像サイズを変更する方法

フィルターフックで画像サイズを変更する方法

テンプレートを編集せずに済ませたい場合は、Tutor LMSが提供するフィルターフックを利用する。functions.php に数行追加するだけで、コースループで呼び出される画像サイズを変更できる。

functions.phpにフィルターを追加する

子テーマの functions.php に以下のコードを追加する。tutor_course_thumbnail_size フックは、コースループで使われるサムネイルサイズを差し替えるためのものだ。

add_filter('tutor_course_thumbnail_size', function($size) {
    return 'full';
});

このコードは、Tutor LMSがコースカードのサムネイルを出力する際に参照するサイズ名を full に上書きする。元画像が十分な解像度でアップロードされていれば、一覧表示でも鮮明になる。

なお、プラグインのバージョンや使用中のテーマによってフック名の実装が異なる場合がある。テンプレート上書きの方が確実に効くため、フィルターで変化が見られない場合はテンプレート上書きに切り替えるのが確実だ。

サムネイル再生成とキャッシュのクリア

サムネイル再生成とキャッシュのクリア

画像サイズの指定を変更した後は、既存の画像に対して新しいサイズのサムネイルが生成されていない場合がある。特に full サイズを使う場合は元画像そのものを参照するため再生成は不要だが、large や独自サイズを使う場合は再生成が必要になる。

サムネイル再生成で古いサイズを更新する

「Regenerate Thumbnails」などの再生成プラグインを使うと、WordPressに登録されている全画像サイズを一括で作り直せる。再生成の所要時間は画像点数に依存するが、数百枚程度なら数分で完了する。

サイトキャッシュとブラウザキャッシュを削除する

変更後に表示が古いままの場合は、キャッシュ系プラグインの全削除と、ブラウザのキャッシュクリアを行う。CDNを利用している場合は、CDN側のキャッシュもパージする。これで新しい画像サイズがサーバーから配信される。

変更後チェック
サイズ変更 再生成 キャッシュ削除 表示確認
設定変更  再生成  キャッシュ

このデモは、画像サイズ変更後に確認すべき作業の流れを示している。

よくある質問

Tutor LMSのコース画像サイズはどこで登録されているのか?

Tutor LMSはプラグインのコード内で add_image_size() 関数を使って専用サイズを登録している。登録名は tutor-course-thumbnail などで、コースループ用テンプレートがこのサイズを参照する。標準のWordPress設定画面からは変更できない。

子テーマを作っていない場合はどうすればよいか?

まず子テーマを作成する。WordPress公式ドキュメントに従い、style.cssfunctions.php を含むフォルダを作成すればよい。親テーマを直接編集するとアップデートで変更が消えるため、子テーマ運用が安全だ。

画像を変更しても古いサイズのまま表示されるのはなぜか?

ブラウザキャッシュやサイトキャッシュが古い画像を保持している可能性が高い。キャッシュ系プラグインの全削除と、ブラウザのキャッシュクリアを行う。CDNを使っているならCDN側のパージも必要だ。

フィルターフックが効かない場合はどうする?

プラグインのバージョンやテーマの構造によって、特定のフックが実装されていない場合がある。その場合はテンプレート上書き方式に切り替える。テンプレートファイル内のサイズ指定を直接書き換えれば、フックの有無に関係なく確実に反映される。

CSSだけで画像を鮮明にできるか?

できない。CSSで image-rendering プロパティを調整しても、元の画像データが小さい限り拡大によるぼやけは残る。根本的な解決には、テンプレートやフィルターで大きなサイズの画像を呼び出す必要がある。

この記事のポイント

  • Tutor LMSのコース画像ぼやけは小さい専用サイズの参照が原因
  • 子テーマへのテンプレート上書きで確実に修正できる
  • フィルターフックでもサイズ変更が可能
  • サイズ変更後は再生成とキャッシュ削除が必須
  • CSSだけでは根本解決にならない
WP Offload Mediaでサイトに重大なエラーが発生した時の原因と対処法

WP Offload Mediaでサイトに重大なエラーが発生した時の原因と対処法

WP Offload Media(S3/CloudFrontにメディアを転送するプラグイン)でサイトに「このサイトで重大なエラーが発生しました」と表示され、画面が表示されなくなる場合、PHP 8.xではプラグイン内部のsprintf()呼び出しに引数が1つ足りないのが原因だ。最新版へのアップデートで解消する。

なぜWP Offload MediaでArgumentCountErrorが起きるのか

なぜWP Offload MediaでArgumentCountErrorが起きるのか

このエラーの直接の原因は、WP Offload Mediaの remove-local-handler.php 内にある sprintf() 呼び出しだ。メディアをS3へ転送(オフロード)した後、ローカルファイルを削除しようとして失敗すると、エラーメッセージを整形する処理が走る。その際、翻訳文字列にファイルパス用の %s が含まれているのに、実際のファイルパスが渡されていない。

PHP 7.xまでは引数不足の sprintf() は警告で済んでいた。ところが PHP 8.0 以降では ArgumentCountError という致命的エラーになり、未処理の例外としてサイト全体が停止する。本来なら所有権やパーミッションの警告で済むはずの内部メッセージ生成が、フロントエンド全体を落とす事態になる。

発火のきっかけは特定の操作に限らない。Yoast SEO のスキーマ生成が wp_head 内で wp_get_attachment_image_url() を呼ぶケースもある。カスタム投稿やギャラリー、商品ページのサムネイル取得など、アップロード済みメディアの URL を取得する場所ならどこでも起こり得る。

Before(エラー状態)
sprintf() にフォーマット文字列だけを渡し、%s 用のファイルパスが無い。PHP 8が ArgumentCountError を投げ、サイト全体が停止する。
After(修正後)
sprintf() の第2引数に $file を渡す。エラーは警告として記録されるだけで、サイトは稼働を続ける。
エラー状態  修正後

修正版では sprintf() の第2引数として $file(実際のファイルパス)が追加される。未処理の例外がなくなるため、フロントエンドの停止を防げる。

エラーログから原因の関数名を確認する手順

エラーログから原因の関数名を確認する手順

画面上では「このサイトで重大なエラーが発生しました」とだけ表示され、詳細はわからない。管理者宛のメールやサーバーのPHPエラーログにスタックトレースが残っている場合もあるが、WordPress の debug.log を有効にするのが最も確実だ。

  • wp-config.php をテキストエディタかFTPで開く
  • WP_DEBUG と WP_DEBUG_LOG を true にして保存する
  • エラーが起きたページを再読み込みする
  • wp-content/debug.log を開き、ArgumentCountError と Remove_Local_Handler を探す

スタックトレースに「2 arguments are required, 1 given」という記述があれば、この症状と一致する。Yoast SEO が呼び出し元に含まれる場合もあるが、他のプラグインやテーマ由来でも発火するため、関数名の確認を優先する。

WP Offload Mediaをアップデートして修正する手順

WP Offload Mediaをアップデートして修正する手順

修正が取り込まれたバージョンがリリースされていれば、管理画面からプラグインを更新するのが最短の対応だ。WP Offload Media はサブスクリプション型のライセンスで更新が配布されるため、ライセンスが有効かどうかも確認しておく。

STEP 1 管理画面の「プラグイン」を開く
STEP 2 WP Offload Media に更新があるか確認する
STEP 3 プラグインを更新する
STEP 4 キャッシュを削除し、ページの復旧を確認する

更新後はサーバーキャッシュとブラウザキャッシュを削除してから、エラーが出ていたページを開き直す。WP CLI を使える環境では wp plugin update コマンドでも更新できる。

すぐに更新できない場合の一時的な対処

すぐに更新できない場合の一時的な対処

サブスクリプションの期限切れなどで更新が受けられない場合は、remove-local-handler.php に直接修正を加える方法がある。管理画面の「プラグイン」メニューにある「プラグインファイルエディター」からWP Offload Media を選び、remove-local-handler.php を開く。

sprintf() に $file を追加して回避する

修正箇所は2つある。remove-local-handler.php の180行付近と185行付近だ。どちらも sprintf() の閉じ括弧の前に、カンマと $file を追加する。このファイルはプラグイン本体のため、次回のアップデートで上書きされるが、修正版が配布されるまでの時間稼ぎにはなる。

// 修正前(180行付近)
$file_to_remove['remove_result']['message'] = sprintf(
    __( "Error removing local file. Couldn't find the file at %s", 'amazon-s3-and-cloudfront' )
);

// 修正後
$file_to_remove['remove_result']['message'] = sprintf(
    __( "Error removing local file. Couldn't find the file at %s", 'amazon-s3-and-cloudfront' ),
    $file
);

// 185行付近も同様に $file を追加する

プラグインを一時的に無効化する

管理画面に入れる場合は、WP Offload Media を一時的に無効化すればサイトは復旧する。ただし、メディアがすでにS3にオフロードされていると、無効化中はローカルに存在しない画像が表示されないことがある。緊急時の対応と割り切って使う。

PHPバージョンを7.4に戻す

サーバーの設定で PHP を 7.4系に戻せばエラーは出なくなる。ただし、PHP 7.4はセキュリティサポートが終了しているため、恒久対策にはならない。あくまで更新までの一時的な回避策だ。

所有権とパーミッションを見直して再発を防ぐ

所有権とパーミッションを見直して再発を防ぐ

このエラーが起きたということは、オフロード後に削除するはずのローカルファイルに削除権限がなかった可能性が高い。プラグインの修正後は、アップロードディレクトリの所有権とパーミッションを確認し、Webサーバーユーザーが書き込める状態にしておく。

アップロードディレクトリ(wp-content/uploads)は、ディレクトリが755、ファイルが644であることが一般的だ。所有権がFTPユーザーになっていると、Webサーバープロセスが削除できず同じ状態になる。サーバー管理画面やシェルから、アップロードディレクトリの所有者をWebサーバーの実行ユーザーに合わせる。

# 所有者とグループをWebサーバー実行ユーザーに合わせる(www-data は環境により異なる)
sudo chown -R www-data:www-data wp-content/uploads

# ディレクトリとファイルの権限を整える
find wp-content/uploads -type d -exec chmod 755 {} \;
find wp-content/uploads -type f -exec chmod 644 {} \;

実行ユーザーの名前はサーバー環境によって www-data、apache、nginx など異なる。レンタルサーバーでは管理画面のファイルマネージャーから所有者を変更できないこともあるため、その場合はカスタマーサポートに依頼するか、PHP を実行ユーザーと同じ権限で動かす設定を検討する。

よくある質問

管理画面にも入れないほど真っ白になった場合はどうする?

FTPやサーバーのファイルマネージャーから wp-content/plugins/ に入り、WP Offload Media のフォルダ名を「WP Offload Media_backup」のように変更して無効化する。WordPress はプラグインが存在しないと認識し、サイトを復旧できる。その後、原因を修正してからフォルダ名を元に戻す。

プラグインを更新したのにまだエラーが出るのはなぜ?

キャッシュが残っている可能性が高い。サーバーキャッシュとブラウザキャッシュを削除してから再確認する。それでも出る場合は、別のプラグインが同様の sprintf() 引数不足を起こしている。デバッグログのスタックトレースを再確認する。

ArgumentCountError は WP Offload Media 以外でも起きる?

起きる。PHP 8.0以降では、翻訳文字列に %s を含む sprintf() で引数を渡し忘れると同様の致命的エラーになる。古いテーマやプラグインで潜伏していることが多い。PHP 8.x へ移行する際は事前にステージング環境でテストするのが基本だ。

所有権の問題を放置するとどうなる?

ローカルファイルの削除が失敗し続け、アップロードディレクトリに同じファイルが重複して残る。ディスク容量やバックアップサイズにも影響する。プラグイン自体は修正されても、警告ログが出続けるため、所有権は合わせて直しておくべきだ。

この記事のポイント

  • WP Offload Media の sprintf() 引数不足が PHP 8.x で致命的エラーになる
  • 「このサイトで重大なエラーが発生しました」の裏で ArgumentCountError が起きている
  • 修正版への更新が最短の解決策
  • 更新できない間は sprintf() の第2引数に $file を追加する
  • 所有権とパーミッションを整えて同じ失敗が起きないようにする
WordPress 7.1正式版が8月19日リリース。レスポンシブスタイルと疑似状態の全容

WordPress 7.1正式版が8月19日リリース。レスポンシブスタイルと疑似状態の全容

WordPress 7.1の正式版が2026年8月19日にリリースされる。WordCamp US最終日と重なるタイミングで、すでにRC1とRC2が公開され、機能セットは確定済みだ。先月にはセキュリティリリース2件も出ており、影響を受けるサイトは自動更新が強制された。

今回のアップデートで注目が大きいのは、レスポンシブブロックスタイルと疑似状態スタイルのコア導入だ。テーマ開発者はモバイルとタブレットの表示をtheme.jsonだけで制御できるようになる。プラグイン開発者もリストテーブルの構造変更に注意が必要だ。正式版まで残り数日、互換性確認のポイントを解説する。

WordPress 7.1は8月19日リリース、RC2まで公開済み

WordPress 7.1は8月19日リリース、RC2まで公開済み

正式版はWordCamp US最終日に到着

WordPress 7.1は8月19日にリリース予定だ。ちょうど8月16日から19日にかけて米国フェニックスで開催されるWordCamp USの最終日と重なる。年次フラッグシップイベントの最終日に正式版が出るのは珍しいスケジュールで、現地参加者はその瞬間をライブで目撃できる。

先週までにRC1とRC2が立て続けに公開された。RC(Release Candidate / リリース候補版)とは、正式版の一歩手前の段階だ。ここまで来ると新機能の追加は終了し、バグ修正だけが行われる。Field Guideも公開済みで、全機能の開発者向け詳細がまとまっている。

セキュリティリリース2件、強制自動更新も発動

先月はセキュリティリリースが2件公開された。7月17日に出たWordPress 7.0.2は、重大な脆弱性1件と高深刻度の脆弱性1件に対処したものだ。深刻度が高かったため、影響を受けるバージョンのサイトには強制自動更新が適用された。続いて8月6日には7.0.3が公開され、十数件の追加修正が入っている。

管理しているサイトが両方の自動更新を何らかの理由で逃していた場合、先にそちらの更新を済ませることが最優先になる。7.1のテストはその後でかまわない。

レスポンシブスタイルがコアに登場

レスポンシブスタイルがコアに登場
デスクトップビュー(デフォルト)
パディング幅 3rem(約48px)
theme.json のデフォルト値がそのまま適用される
タブレットビュー(@tablet)
パディング幅 2rem(約32px)
782px 以下の画面で適用される
モバイルビュー(@mobile)
パディング幅 1rem(約16px)
480px 以下の画面で適用される

上記の図は、theme.jsonでデスクトップ・タブレット・モバイルのパディングを切り替える様子を視覚化したものだ。実際には端末の画面幅に応じて、この3つの状態が自動的に切り替わる。

theme.jsonでモバイルとタブレットのスタイルを定義

春先から開発が進められていたレスポンシブスタイルが、WordPress 7.1で正式にコアに導入された。ブロックのスタイルをタブレットとモバイルのビューポートごとに定義できる。Global Styles(グローバルスタイル)ではブロックタイプ単位で、個別のブロック単位でも設定可能だ。theme.jsonでは@mobile@tabletというキーの中にネストして記述する。

ここで押さえておきたいのは、@desktopキーが存在しない点だ。ブロックのデフォルトスタイルがそのままデスクトップスタイルになる。モバイルやタブレットで上書きしなかったプロパティは、すべてのビューポートでデフォルト値が適用される。

さらにテーマ側でブレークポイントを設定できる。theme.jsonのトップレベルにsettings.viewportプロパティを追加する仕組みだ。デフォルトはモバイルが480px、タブレットが782px。値はpx、em、remの非負の長さのみ許可され、CSS関数やパーセント、単位なしの値は無視される。タブレット値がモバイル値と同じか小さい場合は、モバイルのみが使われる。

標準ブロックサポートを使っているブロックは、タイポグラフィ、カラー、背景、ボーダー、寸法、スペーシング、レイアウトが自動的に対応する。逆に独自のスタイルコントロールを持つブロックは対象外だ。自作ブロックがある場合、この線引きで対応有無を確認してほしい。

疑似状態スタイルでホバーやフォーカスを制御

ボタンの疑似状態スタイル(4状態)
通常状態 ボタン
ホバー状態 ボタン
フォーカス状態 ボタン
アクティブ状態 ボタン
通常  ホバー  フォーカス枠  アクティブ

ホバーやフォーカスは実際の操作で状態が変わるため、上記は4つの状態を並べて示したものだ。実際の編集画面では「Hover」タブを選んでスタイルを設定する。

かねてから要望の多かった疑似状態スタイルも7.1で実装された。:hover:focus:focus-visible:activeをtheme.jsonとエディタで定義できる。現時点ではButtonブロックとNavigation Linkブロックに限定されている。

さらに初期段階のカスタムステート機能も入った。現状はtheme.jsonのみで、管理画面のUIはまだない。Navigation Linkブロックが現在のメニュー項目をスタイルするために-currentプロパティを使う仕組みだ。カスタムステートは-接頭辞を使い、ブロックのblock.jsonにあるselectors.statesプロパティで宣言したクラス名をターゲットにCSSを生成する。現時点では限定的だが、今後の拡張に向けた重要な布石だ。

新しいデザインツール3点

新しいデザインツール3点

テーマ開発者が長年待っていた変更を含む、デザインツールの追加が3つある。グラデーションと背景画像を同時に使えるようになるのは特に大きい。

背景グラデーションと背景画像を併用可能に

新しいbackground.gradientは既存のcolor.gradientとは別のサポートとして追加された。違いはCSSの出力先にある。従来のサポートはbackgroundショートハンドを通じて描画されるため、background-imageを含むすべてのbackground関連プロパティをリセットしてしまっていた。ブロックにグラデーションか画像のどちらか一方しか使えなかった理由だ。

新しいサポートはbackground-imageロングハンドで描画される。スタイルエンジンが1つの宣言内にグラデーションと画像をカンマ区切りで出力できるようになった。7.1ではGroup、Accordion、Pullquote、Post Content、Quoteがコアで対応する。値はstyle.background.gradientに保存される。

最小幅とテキストシャドウ

dimensions.minWidthは既存のminHeightと同じパターンで、CSSのmin-widthとして適用される。テーマがdimensionSizesプリセットを提供していれば、それを活用できる。1点注意があり、この設定はデフォルトではブロックインスペクターに表示されない。ブロック側で__experimentalDefaultControlsを通じてopt-inした場合のみ表示される。Global Stylesではデフォルトで表示される。

テキストシャドウもGlobal Stylesでサポートされた。これまでは個別ブロックやCSSでしか指定できなかったが、theme.jsonからサイト全体またはブロックタイプ単位で制御できる。

SVG Icon APIが正式公開

アイコン名の衝突を防ぐ名前空間の仕組み
名前空間なしの場合(衝突する)
core / star my-plugin / star 同じ名前で衝突
名前空間を付けた場合(安全)
core/star my-plugin/star それぞれ別のアイコンとして識別

アイコン名の衝突を防ぐため、コレクション名が名前空間の接頭辞になる。プラグイン独自のアイコンを登録しても、コアのアイコンと混同される心配がない。

WordPress 7.0でエディタとIconブロック向けにSVGアイコンのセットが同梱された。7.1ではこれが正式な公開APIになり、プラグインやテーマから登録できるようになった。wp_register_icon_collection()でコレクションを登録し、wp_register_icon()でアイコンを追加する。PHPの任意の場所でwp_get_icon()を使えば、サイズやクラス、ラベルを指定してアイコンを表示できる。

計画時に意識したい制限が2つある。登録したSVGはwp_ksesによって保守的な許可リストでサニタイズされる。許可されるのは<svg><path><polygon>のみ。許可リストの拡大作業は進行中だ。fillは図形部分にのみ許可され、外側の<svg>には付けられない。またwp_get_icon()単体で呼び出すとSVG自身のfill(黒)で描画される。周囲のテキスト色に合わせたい場合は、渡したクラスに対して自前でCSSを指定するのが推奨される。

エディタのiframe化とプラグインへの影響

エディタのiframe化とプラグインへの影響

投稿エディタは常時iframe表示へ

テンプレートエディタがiframe化されたのはWordPress 5.8からだ。それ以来、投稿エディタも段階的に移行してきたが、7.1で最終段階に入った。テーマの種類や登録ブロックのAPIバージョン、コンテンツ内のブロックのAPIバージョンに関係なく、投稿エディタは常にiframeで表示される。レガシーメタボックスを登録しているサイトも同様だ。

7.0では投稿ごとに挿入されたブロックに基づいて判断されていた。つまりコンテンツによってiframedモードと非iframedモードが切り替わり得た。この条件付き動作がなくなり、挙動が単純化された。

大半のブロックは変更なしで動作する。問題が起きる場合、ほとんどは1つの根本原因にたどり着く。iframeは管理者ページとは別のdocumentとwindowを持つ。エディタスクリプトが実行される管理者ページからグローバルのdocumentやwindowにアクセスしてキャンバスを操作しようとすると、間違ったドキュメントを見ていることになる。対処としては、キャンバス内の要素からownerDocumentdefaultViewでドキュメントを取得するか、useRefEffectでキャンバス要素にリスナーをアタッチ・クリーンアップするのが一般的だ。

リストテーブルの行ヘッダーが移動

カスタムCSSやJavaScriptを書いているプラグインにとって、静かに何かを壊す可能性が高いのがリストテーブルの変更だ。投稿一覧テーブルで、プライマリのth scope="row"がチェックボックス列からタイトル列に移動した。チェックボックスセルはtdになり、タイトルセルがthとして投稿タイトルを含むaria-labelを持つ。レスポンシブ表示で折りたたまれるセルはflexレイアウトを使うようになった。

これはアクセシビリティの大きな改善だ。スクリーンリーダーは各行を、場合によっては存在しないチェックボックスではなく投稿名で認識できるようになる。ただしこのマークアップは2010年以降ほぼ安定していたため、多くの拡張が暗黙的に依存している。th.check-columnを選択するCSSやJavaScript、td内の行アクションや投稿タイトルを期待するコードがある場合は確認が必要だ。

この記事のポイント

  • WordPress 7.1は8月19日リリース予定、RC2まで公開済みで機能セットは確定
  • セキュリティリリース7.0.2と7.0.3が先月公開され、強制自動更新も適用された
  • レスポンシブスタイルがコアに入り、モバイルとタブレットのスタイルをtheme.jsonで定義可能に
  • 疑似状態スタイルでホバー、フォーカス、アクティブをテーマから制御できる
  • SVG Icon APIが公開され、プラグインが名前空間付きでアイコンを登録可能に
  • 投稿エディタは常時iframe化され、リストテーブルの行ヘッダー移動も要確認
admin-ajax.phpへのボット大量アクセスでCPUが100%になる時の遮断と対策

admin-ajax.phpへのボット大量アクセスでCPUが100%になる時の遮断と対策

admin-ajax.php へのボットの大量リクエストでサーバーの CPU 使用率が 100% に張り付く場合は、一括遮断ではなく攻撃対象の AJAX アクションをログから特定し、不要な処理を止めた上で正規アクセスを通すレート制限を導入するのが現実的な対策だ。

なぜボットは admin-ajax.php を集中的に叩くのか

admin-ajax.php は WordPress が全 AJAX リクエストを受け付ける入口にあたるファイルだ。フォーム送信、商品カートの更新、ハートビート API による自動保存など、フロントエンドと管理画面の両方で使われている。

ボットがここを狙う理由は、ログイン不要でアクセスできる公開エンドポイントでありながら、リクエストごとに WordPress 全体を読み込んで PHP を実行するため、少ないリクエスト数でもサーバー負荷を大きくできる点にある。

URL に action パラメータを付けて呼び出す構造になっており、たとえば問い合わせフォームの送信処理、EC サイトのカート更新、管理画面の自動保存など、あらゆる AJAX 処理がここを通る。ボットはこれを悪用し、処理の重い action を何度も叩いてサーバーを圧迫する。

攻撃対象の AJAX アクションをログから特定する

攻撃対象の AJAX アクションをログから特定する

対策の最初の一歩は、どの action が攻撃されているのかをアクセスログで確認することだ。闇雲に遮断ルールを増やしても、正規のフォームを巻き込むだけで根本解決にはならない。

アクセスログで action パラメータを調べる

Apache なら /var/log/apache2/access.log、nginx なら /var/log/nginx/access.log にリクエスト履歴が残っている。admin-ajax.php を含む行を抽出し、action= の後ろに続く値を集計すると、攻撃対象が見えてくる。

サーバー管理画面からログをダウンロードできる場合も多い。Cloudflare を利用しているなら、分析画面のセキュリティイベントから admin-ajax.php 宛てのリクエストを絞り込み、クエリ文字列を確認する手もある。

STEP 1 アクセスログで admin-ajax.php へのリクエストを抽出する
STEP 2 action パラメータの値を集計して攻撃対象を特定する
STEP 3 不要なアクションを WordPress 側で無効化する
STEP 4 正規アクセスを通すレート制限を導入する

攻撃対象を特定せずに全リクエストを遮断すると、問い合わせフォームが動かなくなる原因になる。必ずログ調査から始めるのが安全だ。

代表的な攻撃対象を把握しておく

攻撃対象になりやすいのは、外部から呼び出せる未ログインユーザー向けの AJAX アクションだ。問い合わせフォームの送信処理、ハートビート API の更新処理、EC サイトのカート更新などが代表例になる。自分のサイトに不要なプラグインが残した action がしばしば悪用される。

正規のフォームを壊さずにレート制限する

正規のフォームを壊さずにレート制限する

すべての admin-ajax.php リクエストにチャレンジ(CAPTCHA や JS チャレンジ)を適用すると、ブラウザ内の JavaScript が裏で送る AJAX リクエストまで巻き込まれ、フォームが正常に動作しなくなる。これが一括チャレンジ方式が失敗する理由だ。

有効なのは、攻撃対象の action だけを条件にしたレート制限だ。単位時間あたりのリクエスト数を IP アドレスごとに制限し、上限を超えたら一時的にブロックする。正規ユーザーのフォーム送信は頻度が低いため、まず引っかからない。

Before 全リクエストにチャレンジを適用
ブラウザ内の AJAX リクエストがチャレンジに引っかかり、問い合わせフォームが送信できなくなる
正規ユーザーまでブロックしてしまう
After 攻撃対象の action だけをレート制限
頻度の低い正規のフォーム送信は通過し、ボットだけが制限を超えてブロックされる
正規ユーザーへの影響を最小限に抑える
一括遮断の失敗例  レート制限による解決

レート制限の閾値は、通常のフォーム送信頻度を大きく上回る値に設定する。たとえば同一 IP から 1 分間に 30 回を超える admin-ajax.php へのリクエストを制限する場合、正規ユーザーが 30 回もフォームを送ることはない。

WordPress側で不要な AJAX アクションを無効化する

WordPress側で不要な AJAX アクションを無効化する

攻撃対象のアクションが自分のサイトで使われていないなら、WordPress のフックを使ってそのアクション自体を止めてしまうのが最も確実だ。リクエストが届いても処理が実行されず、サーバー負荷は大きく下がる。

未ログインユーザー向けのアクションを止める

wp_ajax_nopriv_ から始まるフックは未ログインの訪問者からの AJAX 処理を担当する。使っていない action を特定したら、テーマの functions.php に下のコードを追加して 403 を返すようにする。

add_action('admin_init', function() {
    if (defined('DOING_AJAX') && DOING_AJAX) {
        $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
        if (in_array($action, array('unused_action_1', 'unused_action_2'), true)) {
            wp_die('403 Forbidden', 'Forbidden', array('response' => 403));
        }
    }
}, 1);

action 名はログで特定した値に置き換える。これで、その action へのリクエストは WordPress の初期化直後に拒否され、プラグインのコードが呼ばれる前に処理が終わる。

ハートビート API の負荷を下げる

管理画面や投稿編集画面で自動保存・ロック通知のために heartbeat が一定間隔で動く。編集画面を開きっぱなしにするボットがいると負荷がかさむ。管理画面を普段使わないサイトなら、heartbeat の頻度を下げるか停止する手もある。

add_filter('heartbeat_settings', function($settings) {
    $settings['interval'] = 300;
    return $settings;
});

interval の単位は秒だ。300 にすると編集画面の自動保存間隔が 5 分になり、サーバーへの負荷が大きく減る。完全に止めるのは編集画面のロック機能に影響するため、まず間隔を延ばすところから始めるとよい。

サーバー設定でボットを直接遮断する

サーバー設定でボットを直接遮断する

Cloudflare やサーバーレベルの設定でも、条件付きの遮断やレート制限を入れられる。正規のフォームを止めずにボットだけを弾くには、リファラー情報やリクエスト頻度を条件に使うのがポイントだ。

リファラーを条件に弾く

正規の AJAX リクエストは、自分のサイトのページから送られるため Referer ヘッダーに自ドメインが入る。一方、ボットは Referer なしや偽装した値で送ることが多い。Apache なら .htaccess で Referer を条件に遮断できる。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} /wp-admin/admin-ajax.php
RewriteCond %{HTTP_REFERER} !^https?://example.com/ [NC]
RewriteRule ^ - [F,L]
</IfModule>

これは自ドメイン以外からの Referer を持つ admin-ajax.php リクエストを 403 で拒否する設定だ。example.com の部分は自分のドメインに置き換える。ただし一部のブラウザ設定で Referer が送られないケースもあるため、完全な遮断には向かない。あくまで補助的な対策として使う。

nginx でレート制限する

nginx を使っているなら limit_req ディレクティブで admin-ajax.php 専用のレート制限を定義できる。サーバーブロックに以下の設定を追加する。

limit_req_zone $binary_remote_addr zone=ajax:10m rate=1r/s;

location = /wp-admin/admin-ajax.php {
    limit_req zone=ajax burst=20 nodelay;
    limit_req_status 429;
    fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
    include fastcgi_params;
}

この設定では、同一 IP から 1 秒あたり 1 リクエストを超えると、バースト(突発的な超過)が 20 回まで許容される。超過分は 429(Too Many Requests)で拒否される。正規ユーザーのフォーム送信はこの制限内に収まるが、ボットの連打はすぐに上限を超える。

よくある質問

すべての admin-ajax.php リクエストを遮断してもよいか

やめておいたほうがよい。問い合わせフォーム、カート更新、検索機能など、多くのサイトで admin-ajax.php が使われている。全遮断すると重要な機能が動作しなくなる。

Cloudflare の Bot Fight Mode だけでは不十分なのか

Bot Fight Mode は既知のボットを自動判定して弾く基本的な防御で、未知のボットや単純なスクリプトには効果が薄い。特定のエンドポイントを狙う攻撃には、レート制限やアクション単位の対策を組み合わせる必要がある。

アクセスログの場所がわからない場合はどうするか

レンタルサーバーの管理画面にアクセスログの閲覧機能があることが多い。わからなければサーバー会社のサポートに問い合わせるか、Cloudflare の分析画面でリクエスト履歴を確認するとよい。

ボット対策プラグインだけでも解決できるか

Wordfence や Limit Login Attempts Reloaded のようなセキュリティプラグインは総合的な保護を提供するが、admin-ajax.php への大量アクセスには専用のレート制限やサーバー設定のほうが効果的な場合が多い。プラグインとサーバー設定の併用が望ましい。

この記事のポイント

  • admin-ajax.php は公開エンドポイントで、ボットが少ないリクエスト数でも負荷をかける
  • まずアクセスログで action パラメータを集計し、攻撃対象を特定する
  • 一括チャレンジは正規フォームを壊すため、action 単位のレート制限を使う
  • 使っていない AJAX アクションは functions.php から 403 で拒否する
  • サーバー設定(.htaccess や nginx)でも Referer 条件や limit_req で守れる
UpdraftPlusのバックアップが途中で失敗する原因と対処法

UpdraftPlusのバックアップが途中で失敗する原因と対処法

UpdraftPlusのバックアップが途中で止まって失敗する場合、まず確認すべきはセマフォロックの詰まりとサーバー側の実行時間制限だ。ログにエラーが表示されず、ファイル追加の途中で途切れているなら、バックアップ処理がサーバーから強制終了されている可能性が高い。

バックアップが途中で失敗する原因をログから特定する

バックアップが途中で失敗する原因をログから特定する

UpdraftPlusのログに「このサイトで重大なエラーが発生しました」のような明確なメッセージがなく、zipファイルへのファイル追加が途中で止まっている場合、原因のほとんどはバックアップ処理が外部から強制終了されたことにある。ログの末尾に「失敗」や「エラー」の表記がなく、単に記録が終わっている点が重要な手がかりだ。

具体的には、以下の3つのポイントをログから読み取る。1つ目は冒頭の「Semaphore(セマフォ)」に関する記述だ。「Semaphore was stuck」と表示されているなら、前回のバックアップがクラッシュしてロックが残ったままになっていたことを示している。2つ目は処理中に「cgi-fcgi」と記録されている点で、FastCGI経由でPHPが動いている証拠だ。3つ目はファイル追加の記録が数千件単位で正常に進んだ後、突然途切れている点だ。

異常パターン ログの末尾にエラー文言がなく、ファイル追加の途中で記録が止まる
正常パターン 「The backup apparently succeeded」等の完了メッセージが末尾に記録される
強制終了の特徴  正常完了の特徴

上のデモは、強制終了されたバックアップと正常に完了したバックアップのログ末尾の違いを示したものだ。UpdraftPlusのログはバックアップが正常に終わった場合、末尾に完了を示すメッセージが必ず記録される。エラー文言も完了メッセージもないまま記録が途切れているなら、PHPのプロセスごと外部から停止されたと判断できる。

セマフォロックの詰まりが起きる仕組み

セマフォロックとは、同時に複数のバックアップが走らないようにするための「占有フラグ」だ。バックアップ開始時にWordPressのオプションテーブル(wp_options)にロック用の値を書き込み、終了時に削除する。しかし、サーバーが処理を強制終了した場合、ロックを削除する処理まで到達できないため、古いロックが残ってしまう。

残ったロックは次回のバックアップ開始時に「stuck(詰まっている)」と判定され、UpdraftPlusが自動的にリセットする。ログに「Semaphore was stuck, reset to 1」と出ていれば、これは前回のバックアップが異常終了した履歴を示している。ロックの詰まり自体は自動回復するが、その前の回でなぜ強制終了されたのかを解決しなければ、同じ失敗を繰り返す。

セマフォロックの詰まりを解消してから再実行する手順

セマフォロックの詰まりを解消してから再実行する手順

ロックの詰まりが記録されている場合、まずは古いロックを手動で削除してからバックアップを再実行する。UpdraftPlusはロックを自動リセットするが、データベースに古いレコードが残っていると、別の不整合を引き起こすことがある。手動で掃除してから再実行すれば、より確実に状態をリセットできる。

STEP 1 phpMyAdminまたは管理画面からwp_optionsテーブルを開く
STEP 2 「updraftplus_locked_」で始まるレコードを検索して削除する
STEP 3 「updraftplus_last_lock_time_」で始まるレコードもあわせて削除する
STEP 4 UpdraftPlusの「今すぐバックアップ」を実行して動作を確認する

上記の手順でロックを掃除したら、必ずバックアップを即時実行して挙動を確認する。ロックを消しただけでは根本原因は解消されていないため、再び同じ場所で処理が止まるかどうかをログで追う必要がある。もし再び途中で止まるなら、次のセクションで説明するサーバー側の実行制限が原因だ。

wp_optionsテーブルを安全に操作するには

wp_optionsテーブルの操作はレンタルサーバーの管理画面からphpMyAdminを開いて行う。テーブル名はインストール時にプレフィックスを変更している場合があるため、「wp_options」が存在しない場合は「wp_」の部分を導入時に設定した文字列に読み替える。該当するレコードを検索するには、phpMyAdminのSQLタブで「option_name LIKE ‘updraftplus_locked_%’」のような条件を指定すると確実だ。

データベースを直接触るのが不安な場合は、必ず事前にデータベース全体のエクスポートを実行しておく。wp_optionsテーブルはサイト全体の設定を保持する重要なテーブルなので、削除対象を間違えるとサイトが表示されなくなる恐れがある。削除するのは「updraftplus_」で始まるロック関連のレコードだけに限定する。

サーバーの実行時間制限が原因なら設定を見直す

サーバーの実行時間制限が原因なら設定を見直す

ログに「cgi-fcgi」と記録されている環境では、サーバー側のFastCGI設定がバックアップ処理を途中で切断している可能性が高い。この場合、UpdraftPlusやWordPressの設定をいくら変更しても解決しない。サーバーの実行時間制限とプロセス管理の仕組みを理解し、制限内に収まるようにバックアップ規模を調整するか、サーバー側の設定を変更する必要がある。

バックアップ対象を絞って1回あたりの負荷を下げる

処理が途中で強制終了される最も簡単な回避策は、1回のバックアップで処理するデータ量を減らすことだ。UpdraftPlusの設定画面で「ファイルのバックアップ」の対象から、変更頻度の低い大容量ディレクトリを除外する。たとえば、開発用のnode_modulesやキャッシュディレクトリ、過去のバックアップファイルなどは除外候補になる。

データベースのバックアップも同様に、ログや一時テーブル、リビジョンなどを除外すると処理時間を短縮できる。とくに投稿リビジョンやスパムコメント、ゴミ箱内のデータは意外と容量が大きい。不要なデータを定期的に削除するだけでも、バックアップの所要時間が大きく変わる。

zip分割サイズとバッチ処理の調整

UpdraftPlusの詳細設定では、zipファイルを分割するサイズを変更できる。デフォルトでは400MBごとに分割されるが、ファイル数が多いサイトでは分割サイズを小さく設定すると、1回のバッチ処理にかかる時間を短縮できる。ログで「split every 400 MB」と表示されている箇所が、この設定の反映だ。

分割サイズを200MBや100MBに下げると、1回のzip処理が短くなり、サーバーの制限時間内に完了しやすくなる。ただし、分割数を増やすと全体の処理時間は逆に延びるため、サーバーの制限時間に対してどこで止まるかを見極めながら調整する。ログの経過時間と処理件数を確認し、どこまで進んだ時点で強制終了されるかを把握することが先決だ。

バックアップを安定させるための追加対策

バックアップを安定させるための追加対策

ロックの掃除とバックアップ対象の絞り込みに加えて、以下の設定を組み合わせると、UpdraftPlusのバックアップ成功率が大きく向上する。いずれも管理画面から変更できる項目なので、サーバーに詳しくなくても実行できる。

バックアップの実行方法を「手動」から「cron」に切り替える

管理画面から手動でバックアップを実行すると、ブラウザとサーバーの接続が切れたタイミングで処理が中断されることがある。一方、WordPressのcron(疑似cron)を使ったスケジュール実行は、サーバー側で処理が完結するため、ブラウザの接続状態に影響されない。UpdraftPlusの設定で「バックアップのスケジュール」を有効にし、実行タイミングを毎日や毎週などに設定する。

ただし、WordPressの疑似cronはサイトへのアクセスをきっかけに動くため、アクセスの少ないサイトでは実行が遅れることがある。その場合はサーバー側のcron(本物のcron)を設定し、wp-cron.phpを定期的に呼び出す方式に切り替えると確実だ。レンタルサーバーの管理画面からcronジョブを追加できる場合が多い。

バックアップの保存先を外部ストレージに変更する

バックアップをサーバー内のディレクトリに保存していると、バックアップ完了後にファイルを外部へ転送する処理が追加され、時間がかかるだけでなく、転送中のエラーで失敗と記録されることがある。UpdraftPlusはGoogle DriveやDropbox、Amazon S3などへの直接アップロードに対応しているため、外部ストレージを保存先に指定すると、サーバー内への書き込みと転送を1つの流れで行える。

外部ストレージへの保存は、サーバーのディスク容量不足による失敗を防ぐ効果もある。バックアップは数GB単位で容量を消費するため、共用サーバーでは容量制限に達して書き込みに失敗するケースが少なくない。ログの冒頭に「Free space on disk」の値が記録されているので、この数値が数十GB以上確保されているかも確認しておく。

PHPの実行時間とメモリ制限を確認する

ログの冒頭には「max_execution_time」と「memory_limit」が記録されている。max_execution_timeはPHPスクリプトが実行できる最大時間、memory_limitはPHPが使用できるメモリの上限だ。どちらもバックアップ処理に直結する設定で、これらの値が小さいと処理が途中で打ち切られる。

レンタルサーバーによっては、管理画面からPHPのバージョンや設定を変更できる。max_execution_timeを300秒以上、memory_limitを512MB以上に設定できるなら変更を検討する。ただし、共有サーバーでは変更できない場合も多い。その場合は先に説明したバックアップ対象の絞り込みで対応するほうが現実的だ。

よくある質問

ログにエラーが何も表示されません。どこを確認すればいいですか?

ログの末尾に「失敗」や「エラー」の文言がなく記録が途中で止まっている場合、PHPのプロセスがサーバーから強制終了された可能性が高い。ログの経過時間と処理済みファイル数を確認し、どこまで進んだ時点で止まったかを特定する。あわせて冒頭のセマフォロック関連の記述も確認する。

セマフォロックは自動的に解消されますか?

UpdraftPlusは次回のバックアップ開始時に古いロックを自動でリセットする。ただし、原因が解決されていなければ再び同じ場所で強制終了され、ロックの詰まりが繰り返される。手動でロックを掃除したうえで、根本原因であるサーバーの実行制限やバックアップ規模の見直しを行うことが重要だ。

バックアップ対象から除外すべきフォルダはありますか?

キャッシュディレクトリ、過去のバックアップファイル、開発用の依存関係が入ったディレクトリ、ログファイルなどは除外候補になる。とくに「node_modules」や「vendor」のようなディレクトリは数千から数万のファイルを含むことがあり、ファイル数の多さがバックアップを遅くする大きな要因になる。

UpdraftPlusのログはどこで確認できますか?

管理画面の「設定」から「UpdraftPlus バックアップ」を開き、「既存のバックアップ」タブを表示する。各バックアップの横にある「ログを表示」ボタンから詳細なログを確認できる。ログは最新のものから順に表示され、画面上でスクロールしながら全文を確認できる。

バックアップが途中で止まる場合、サーバー会社に問い合わせるべきですか?

レンタルサーバーの管理画面から設定を変更できない項目が原因の場合、サーバー会社への問い合わせが必要になる。問い合わせる際は、UpdraftPlusのログの該当部分を添付し、「バックアップが毎回特定のタイミングで強制終了される」と具体的に伝えると、調査がスムーズに進む。

この記事のポイント

  • ログに完了メッセージがなく途中で止まる場合は強制終了が原因
  • セマフォロックの詰まりは前回の異常終了の痕跡
  • wp_optionsのロック関連レコードを手動で削除して状態をリセット
  • バックアップ対象の絞り込みとzip分割サイズの調整で負荷を下げる
  • cron実行と外部ストレージ保存の組み合わせで成功率を上げる
SureCookieで同意ログが記録されない時の原因と対処法

SureCookieで同意ログが記録されない時の原因と対処法

SureCookie で同意ログが 0 件のまま増えない場合、まず疑うのは REST API の URL が 404 を返している状態だ。パーマリンク設定とキャッシュ・最適化プラグインの影響を順に確認すれば、原因を特定できる。

同意ログが記録されない原因は REST API の URL にある

同意ログが記録されない原因は REST API の URL にある

訪問者が Cookie 同意バナーで「すべて同意」を選ぶと、SureCookie は WordPress の REST API に POST リクエストを送り、同意内容をログへ書き込む。この API とは、サイト内部と外部のスクリプトがデータをやり取りするための仕組みだ。

ところが、サイト側の設定やキャッシュの影響で、送信先の URL が意図した形にならないことがある。正常なら /wp-json/ から始まる URL が使われるが、設定オブジェクトが読み込まれないと /?rest_route= という形式に切り替わる。どちらも本来は動作する形式だが、後者が 404 を返す場合はリクエストが WordPress 本体に届いていない。

ブラウザの開発者ツールでネットワークタブを開き、バナー操作時の POST リクエストを確認すると、404 ステータスが返っている様子を直接確認できる。これが確認できれば、ログが記録されない直接の原因だ。

正常時の URL
パーマリンクが「投稿名」で設定オブジェクトあり
POST 先 /wp-json/surecookie/v1/consent
→ 200 OK でログが保存される
問題が起きる URL
設定オブジェクトが読み込まれていない
POST 先 example.com/?rest_route=/surecookie/v1/consent
→ 404 Not Found でログが残らない
正常時  問題発生時

上図は URL の生成パターンを示したイメージだ。パーマリンク設定が「投稿名」などの見やすい形式にもかかわらず /?rest_route= が出る場合は、SureCookie の設定オブジェクトがページに正しく出力されていない。

パーマリンク設定を確認して URL 形式を切り分ける

パーマリンク設定を確認して URL 形式を切り分ける
STEP 1 パーマリンク設定を確認する
STEP 2 キャッシュと最適化を無効化する
STEP 3 REST API の応答を確認する
STEP 4 同意バナーを操作してログを確認する

この手順の全体像を踏まえて、各ステップを詳しく見ていく。

パーマリンク設定が「基本」の場合

WordPress 管理画面の「設定 → パーマリンク」を開き、現在の設定が「基本」になっている場合、/?rest_route= という URL が使われるのは正常な動作だ。この場合、URL の形式そのものは問題ではなく、404 になる原因は別にある。REST API 自体がブロックされているか、リクエストが WordPress に到達していない可能性を後述の手順で確認する。

パーマリンク設定が「投稿名」の場合

パーマリンク設定が「投稿名」などに設定されていれば、通常は /wp-json/ から始まる URL が使われる。それにもかかわらず /?rest_route= が現れるなら、SureCookie の設定オブジェクトがページ上に出力されていない。パーマリンク設定を一度保存し直し、データベース上のリライトルールを再生成するだけでも改善することがある。

キャッシュと JavaScript 最適化が設定を壊すケース

キャッシュと JavaScript 最適化が設定を壊すケース

サーバー付属の最適化プラグインやキャッシュプラグインが、JavaScript の結合・遅延読み込み・圧縮を実行していると、SureCookie がページに埋め込む設定オブジェクトが壊れるか、出力されないことがある。その結果、プラグインが正しい URL を生成できず、フォールバックとして /?rest_route= を送り、404 になる。

キャッシュの全削除と最適化の停止

最初にキャッシュプラグインの管理画面からキャッシュを全削除する。続いて JavaScript の結合、遅延読み込み、圧縮の各機能を一時的に無効化する。この状態でブラウザのシークレットウィンドウを開き、同意バナーを操作してログが記録されるか確認する。直った場合は、最適化機能のどれかが原因だ。

除外設定を追加して再有効化する

原因が特定できたら、SureCookie のスクリプトを最適化の除外リストに追加する。除外対象は SureCookie の本体スクリプトと、それに付随する設定オブジェクトのインラインスクリプトだ。除外設定後、最適化機能を一つずつ再有効化し、その都度ログが記録されるかを確認する。これで各機能の影響を切り分けられる。

REST API がブロックされていないか確認する

REST API がブロックされていないか確認する

セキュリティプラグインやサーバー側の設定で WordPress の REST API が無効化されていると、/wp-json//?rest_route= も 404 や 403 を返す。同意ログの POST リクエストも同じようにブロックされるため、ログが一切記録されない。

REST API の動作確認

ブラウザのアドレスバーに、自サイトのドメインの直後に /wp-json/ を付けてアクセスする。正常なら JSON 形式のデータが表示される。404 や 403 になる場合は、REST API がサイト全体でブロックされている。セキュリティプラグインの設定画面を開き、REST API を許可するか、SureCookie のエンドポイントを除外する。

ログインユーザー限定設定を見直す

REST API へのアクセスをログインユーザーに限定する設定があると、未ログインの訪問者が送る同意 POST が拒否される。同意バナーを操作するのはログインしていない一般訪問者なので、この設定が有効だとログは永遠に記録されない。該当する設定を無効化するか、SureCookie のエンドポイントだけを許可する。

サイトスキャナーが Cookie を検出しない理由

サイトスキャナーが Cookie を検出しない理由

SureCookie に内蔵されたサイトスキャナーが「成功」と表示しても Cookie を 0 件と報告するのは、同意前のスクリプトブロックが働いているためだ。Google アナリティクス 4(GA4)や Microsoft Clarity のタグは、同意が得られるまで読み込まれない。スキャナーがこのブロック状態で実行されるなら、Cookie を検出しないのは想定内といえる。

一方、外部スキャナーが検出できるのは、実際の訪問者が同意した後にタグが発火し、Cookie が設定された状態を計測しているからだ。SureCookie のスキャナーが同意後の状態を反映するかは、製品のバージョンやスキャンの実行タイミングによって異なる。同意ログと実際の Cookie の乖離が続く場合は、プラグインの仕様や設定を確認する必要がある。

よくある質問

同意ログが記録されないと法的に問題になるか

Cookie 同意の記録は、GDPR や改正電気通信事業法などの監査対応で重要な証跡になる。ログが残っていないと、同意取得の事実を証明できないため、監査や紛争時に不利になる可能性がある。運用前に必ず記録される状態へ直しておく。

/?rest_route= という URL は正常なのか

パーマリンク設定が「基本」であれば、/?rest_route= は WordPress が公式にサポートする正常な形式だ。ただし「投稿名」などに設定しているのにこの形式が出る場合は、設定オブジェクトの読み込みに失敗している可能性が高い。

パーマリンク設定が基本のままでも SureCookie は動くか

動くように設計されている。REST API のリクエストが正しく WordPress に到達すれば、/?rest_route= でも同意ログは記録される。404 になるのは URL の形式だけが原因ではなく、リクエスト経路のどこかでブロックされているケースだ。

キャッシュプラグインの除外設定はどの範囲か

SureCookie の本体スクリプトと、設定オブジェクトを含むインラインスクリプトを対象にする。多くのキャッシュプラグインにはスクリプト単位の除外欄があるため、そこに SureCookie 関連のスクリプト名を追加し、結合や遅延読み込みから外す。

同意ログが記録されたか確認する方法は

SureCookie の管理画面にある同意ログ一覧で件数が増えるかを確認する。あわせてブラウザの開発者ツールで POST リクエストが 200 を返しているかを見ると、書き込みが成功しているかがより正確にわかる。

この記事のポイント

  • 同意ログが残らない直接の原因は REST API の 404 だ
  • パーマリンク設定で URL 形式の正常性を切り分ける
  • キャッシュと JavaScript 最適化を無効化して確認する
  • REST API 自体のブロックも忘れずに点検する
  • スキャナーの Cookie 0 件は同意前ブロックが原因になりやすい
WordPressでデータベース接続確立エラーが出た時の直し方

WordPressでデータベース接続確立エラーが出た時の直し方

WordPressで「データベース接続確立エラー」が表示される原因は、wp-config.phpファイル内のデータベース接続情報の誤り、またはデータベースサーバー自体の停止に大別される。まずはこの二点を順に確認すれば、大半のケースは解決する。

エラーメッセージが示す根本的な原因は二つだけ

エラーメッセージが示す根本的な原因は二つだけ

WordPressのインストール時や運用中に「データベース接続確立エラー」というメッセージが表示された場合、WordPressは設定ファイルに書かれた情報でMySQL(またはMariaDB)データベースへ接続できていない。エラー画面にも表示される通り、原因は大きく分けて次の二つだ。

  • 認証情報の不一致(wp-config.phpのデータベース名、ユーザー名、パスワード、ホスト名のいずれかが間違っている)
  • データベースサーバーに接続できない(サーバーが停止している、ネットワーク障害がある、ホスト名が間違っている)

新規インストール直後のエラーでは設定ミスが大半を占め、運用中のサイトで突然発生した場合はサーバー側の一時的なトラブルや、何らかの設定変更が影響している可能性が高い。いずれにせよ、対処のステップは決まっている。

エラー 「データベース接続確立エラー」が画面に表示される
認証情報 確認

wp-config.phpのDB_NAME・DB_USER・DB_PASSWORD・DB_HOSTを再チェック

サーバー 確認

データベースサーバーが稼働しているか、管理画面から確認

エラー状態  認証情報の確認  サーバー稼働の確認

最初に確認すべきwp-config.phpの設定

最初に確認すべきwp-config.phpの設定

データベース接続情報を記述するwp-config.phpは、WordPressのルートディレクトリに設置されている。エラーが起きたら、まずこのファイルの中身をファイルマネージャーやFTPで開き、以下の4項目が正しいか確認する。

データベース名(DB_NAME)の確認

DB_NAMEには、使用するデータベースの正確な名前を指定する。多くのレンタルサーバーでは、契約時に自動生成されたデータベース名にアカウント名のプレフィックスが付与される(例: username_wp001)。phpMyAdminやサーバー管理画面のMySQLデータベース一覧に表示される名前と、一字一句たがわず一致させる必要がある。大文字小文字も区別されるため、コピー&ペーストで転記するのが確実だ。

ユーザー名(DB_USER)とパスワード(DB_PASSWORD)の精査

データベースに接続するためのユーザー名とパスワードも同様に、サーバー側で作成したMySQLユーザーの情報と完全一致させる。パスワードは暗号化されずに平文で記述されるため、見間違いがないか注意する。また、パスワードに特殊文字(’ ” \ $ など)が含まれていると、PHPが正しく解釈できず接続エラーを引き起こすことがある。必要に応じてシングルクォーテーションで囲む、あるいはパスワード自体を英数字のみの強固なものに変更するのも有効な手段だ。

ホスト名(DB_HOST)の指定

DB_HOSTは、WordPressがデータベースサーバーを探しに行く宛先だ。多くの共用サーバーでは localhost で問題ない。しかし、一部のホスティング環境では、データベースサーバーがWebサーバーとは別のマシンで動作しており、専用のホスト名やIPアドレスが割り当てられている。サーバー会社のマニュアルに記載されているホスト名(例: mysql.example.com)を指定する。稀に 127.0.0.1 で接続できるが localhost だとエラーになるケースもあるため、どちらも試す価値がある。

Before(エラー発生時)
define( 'DB_NAME', 'wordpress' ); /* ← 実在しないDB名 */
define( 'DB_PASSWORD', 'mypassword' ); /* ← 誤ったパスワード */
After(修正後)
define( 'DB_NAME', 'user_wp01' ); /* ← 正しいDB名 */
define( 'DB_PASSWORD', 'C0rrect!Pass#' ); /* ← 正しいパスワード */

データベースサーバーが稼働しているか確認する

データベースサーバーが稼働しているか確認する

wp-config.phpの設定が正しいのにエラーが続く場合、問題はデータベースサーバー側にある。まず、利用しているホスティングサービスの管理画面にログインし、MySQLやデータベースのセクションを確認する。

サーバー管理画面からの状況確認

多くのレンタルサーバーでは、cPanelや独自のコントロールパネルからMySQLサーバーの稼働状況や、データベースの一覧、ユーザー管理が行える。対象のデータベースとユーザーが存在し、かつユーザーに適切な権限が付与されているかを確認する。サーバー会社によっては、メンテナンスや障害発生時にステータスページで告知を行っているため、そちらも合わせてチェックする。

phpMyAdminで直接ログインを試みる

サーバーの管理画面からphpMyAdminを起動し、wp-config.phpで指定したのと同じユーザー名とパスワードでログインできるか試す。ログインできればデータベースサーバー自体は稼働しており、認証情報も正しいことになる。ログインに失敗する場合は、パスワードのリセットやユーザーの再作成を検討する。ローカル環境(LocalWPやXAMPPなど)で作業している場合は、MySQLサービスが起動しているか、タスクマネージャーやサービス一覧で確認する。

STEP 1 サーバー管理画面にログインし、MySQLの項目を開く
STEP 2 データベースとユーザーが存在し、リンクされているか確認
STEP 3 phpMyAdminで同じ認証情報を使ってログインできるかテスト
STEP 4 接続できればデータベースは正常、できなければユーザーの再作成を検討

それでも解決しない場合の追加確認項目

それでも解決しない場合の追加確認項目

上記の確認で問題が見つからない場合、より深い部分に原因が潜んでいる。以下の点を順に見ていく。

データベースユーザーの権限を再確認する

MySQLユーザーがデータベースにアクセスするための権限が不足していると、WordPressはテーブルを作成・読み取りできず接続エラーを起こす。phpMyAdminやサーバー管理画面で、該当ユーザーに「ALL PRIVILEGES」が付与されているか確認する。特にデータベースを移行した直後や、手動でユーザーを作成した場合に起こりやすい。

データベースの破損をチェックする

サーバーの突然の停止やディスク障害により、MySQLのテーブルが破損することがある。phpMyAdminで該当データベースを選択し、すべてのテーブルをチェックして「テーブルの修復」を実行する。WordPressが管理画面にアクセスできる状態であれば、wp-config.phpに define('WP_ALLOW_REPAIR', true); を一時的に追記し、http://example.com/wp-admin/maint/repair.php にアクセスして修復する手段もある。修復後は必ずこの行を削除する。

wp-content/db.php ファイルの存在を疑う

一部のキャッシュプラグインやデータベース置き換えプラグインは、/wp-content/db.php というファイルを作成してWordPress標準のデータベース接続処理を上書きする。このファイルが破損していたり、古い設定を保持したままだと、突然データベース接続エラーを引き起こす。FTPでdb.phpを一時的に別名にリネームし、エラーが消えるか確認する。

マルチサイトのwp-config.php設定を見直す

WordPressのマルチサイト(サブディレクトリ型やサブドメイン型)を運用している場合、wp-config.phpにマルチサイト固有の定義定数が正しく記述されている必要がある。DOMAIN_CURRENT_SITESUBDOMAIN_INSTALL の値が、実際のURL構成やサーバー設定と矛盾していると、内部的なデータベースクエリが失敗して接続エラーに見えることがある。マルチサイト化した直後や、ドメインを変更した後にエラーが起きた場合は、この設定を疑う。

よくある質問

wp-config.phpの修正後にエラーが変わらないのはなぜか

修正内容を保存しても、サーバーのキャッシュやCDN(コンテンツデリバリネットワーク / 配信網)が古いエラー画面を表示し続けることがある。スーパーリロード(Ctrl+F5やCommand+Shift+R)を試し、それでも変わらなければキャッシュ系プラグインを一時停止するか、サーバー側のキャッシュを管理画面からクリアする。

パスワードやユーザー名は合っているのに接続できない

MySQLユーザーが特定のIPアドレスからの接続に制限されている可能性がある。レンタルサーバーでは「localhost」専用のユーザーが作成されるが、外部から接続するように変更してしまうとWebサーバーからのローカル接続が拒否される。phpMyAdminのユーザーアカウント管理で、ホスト名が「localhost」または「127.0.0.1」になっているか確認する。

レンタルサーバーのサポートに連絡するタイミングはいつか

自身でwp-config.phpの設定確認、phpMyAdminからのログインテスト、管理画面からのデータベース稼働状況確認を行っても解決しない場合は、サーバー側の障害や特殊な構成が原因である可能性が高い。サーバー会社のサポートに「WordPressのデータベース接続確立エラーが出ている」「MySQLに接続できない」と具体的に伝えて調査を依頼する。その際、エラーメッセージのスクリーンショットがあるとスムーズだ。

ローカル環境で同じエラーが出る場合の対処法は

LocalWPやXAMPP、MAMPなどのローカル開発環境では、MySQL(またはMariaDB)のサービスが停止していることが原因の大半を占める。各ツールの管理画面で「Start」ボタンを押してサービスを起動し直すか、OSのシステムトレイから再起動する。ポートの競合(特に3306番)が原因で起動に失敗しているケースもあるため、エラーログを確認する。

データベースの修復をしてもすぐにエラーが再発する

テーブルの修復が一時しのぎで終わる場合、ストレージのディスク容量不足や、ハードウェア的な障害が進行している可能性を疑う。サーバーのディスク使用率を確認し、不要なバックアップやログを整理する。根本的にはホスティングサービスのプラン見直しや、サーバー移転を検討する必要がある。

この記事のポイント

  • データベース接続エラーの原因は「認証情報の不一致」と「サーバー停止」に絞られる
  • wp-config.phpのDB_NAME・DB_USER・DB_PASSWORD・DB_HOSTを最初に確認する
  • phpMyAdminで同じ認証情報を用いて直接ログインし、サーバー稼働をテストする
  • 解決しない場合はユーザー権限・DB破損・db.phpの競合・マルチサイト設定を順に疑う
  • サーバー側の障害が疑われる場合は、ログやディスク容量を確認しサポートに連絡する