
WooCommerce Mollie決済プラグイン更新後の致命的エラー対処法
WooCommerce の Mollie 決済プラグイン(Mollie Payments for WooCommerce)をバージョン 8.1.8 から 8.1.9 に更新した直後、サイトに「このサイトで重大なエラーが発生しました」と表示されたり、WordPress から致命的エラーの通知メールが届いたりする場合は、プラグイン内部のコンストラクタが想定する引数の数と実際に渡される引数の数が一致しないことが直接の原因だ。バージョン 8.1.8 へのロールバックで即座に復旧できる。
Mollie プラグイン更新後に起きる致命的エラーの正体とは

今回のエラーは「ArgumentCountError(引数の数が一致しない)」に分類される。具体的には、プラグイン内部の RestApi.php というファイルの 26 行目に定義された __construct() メソッド(クラスの初期化時に呼び出される特別な関数)が 4 つの引数を必要としているにもかかわらず、呼び出し元の services.php 127 行目から 3 つしか渡されていない。
この種の不具合は、プラグインの開発過程でメソッドのシグネチャ(引数の数や型の定義)が変更されたにもかかわらず、すべての呼び出し箇所が追従しなかった場合に発生する。今回のケースでは 8.1.8 から 8.1.9 へのアップデートで RestApi クラスのコンストラクタに新しい依存オブジェクトが 1 つ追加されたが、サービスコンテナ側の定義が更新に追いつかず、3 つのまま残ってしまった可能性が高い。
このエラーは Mollie プラグインの開発元も再現できておらず、特定の環境(PHP バージョンや他のプラグインとの組み合わせ)でのみ発生する。そのため、原因の完全な特定と恒久的な修正には開発元の調査を待つ必要がある。
■ エラーログに「Too few arguments to function」のメッセージ
■ チェックアウトページが動作しない、または管理画面の一部が読み込めない
■ Mollie 決済機能が通常通り動作する
■ 致命的エラーの通知メールが停止する
上図のとおり、ロールバックによってサイトの全機能が即座に回復する。このエラーは PHP の実行を完全に停止させる E_ERROR レベルのため、チェックアウトページを含むサイト全体に影響が及ぶ点が深刻だ。
バージョン 8.1.8 へロールバックして即時復旧する手順

最も確実で安全な対処法は、プラグインを直前の安定バージョンである 8.1.8 に戻すことだ。管理画面にアクセスできる場合とできない場合で手順が異なる。
管理画面にアクセスできる場合のロールバック
管理画面にログインできる状態であれば、WP Rollback プラグインを使うのが最も簡単だ。このプラグインは、WordPress.org の公式プラグインディレクトリに登録された任意のプラグインを、過去の特定バージョンにワンクリックで戻せる。
WP Rollback を使わない場合は、プラグインを一度削除してから旧バージョンを手動でインストールする。削除しても Mollie の API キーや決済設定はデータベースに残るため再設定は不要だが、念のため作業前に WooCommerce のシステムレポートを控えておくと安心だ。
管理画面にもアクセスできない場合の復旧
エラーによって管理画面にも入れなくなっている場合は、FTP クライアントまたはレンタルサーバーのファイルマネージャーを使って対処する。手順は以下のとおりだ。
- FTP でサーバーに接続し、
/wp-content/plugins/ディレクトリに移動する mollie-payments-for-woocommerceフォルダの名前を「mollie-payments-for-woocommerce-broken」などに変更する(これでプラグインが無効化され、管理画面に入れるようになる)- 管理画面にログインしたら、WP Rollback をインストールする
- フォルダ名を元に戻してから、STEP 1〜4 を実行して 8.1.8 にロールバックする
フォルダ名の変更でプラグインを無効化するとサイトのフロントエンドも正常に表示されるようになるが、その間 Mollie 決済は利用できない点に注意する。
手動 ZIP アップロードで 8.1.9 を試す場合の注意点

フォーラムの一部ユーザーは、WordPress 管理画面の自動更新ではなく GitHub からダウンロードした ZIP ファイルを手動アップロードすることでエラーを回避できたと報告している。しかし別のユーザーは同じ手順でもエラーが再発しており、確実な回避策ではない。
手動 ZIP アップロードを試す場合は、以下の点に注意する必要がある。まず、GitHub のリリースページ(Mollie の公式 WooCommerce リポジトリ)から 8.1.9 の ZIP を入手する。プラグイン画面の「新規追加」→「プラグインのアップロード」から ZIP を選択し、「既存のプラグインと置き換える」を確認してアップロードする。
手動アップロード後はサイト全体をくまなく確認し、特に実際のテスト購入でチェックアウトフローが最後まで動作することを確かめる。エラーが再発した場合は速やかに 8.1.8 に戻す。
調査中の自動更新を止めて再発を防ぐ

開発元が修正版をリリースするまでの間、Mollie プラグインが勝手に 8.1.9 に再更新されるのを防ぐ必要がある。WordPress の自動更新設定ではプラグイン単位で自動更新のオンオフを切り替えられる。
「プラグイン」→「インストール済みプラグイン」で Mollie Payments for WooCommerce の行を見ると「自動更新を有効化」または「自動更新を無効化」のリンクがある。これをクリックして自動更新を無効にしておけば、8.1.8 のまま安全に運用を継続できる。修正版がリリースされたら、自動更新を再度有効にしてから手動で更新を実行する。
よくある質問
8.1.8 を使い続けてもセキュリティ上の問題はないか
8.1.8 と 8.1.9 の差分は軽微な機能追加やバグ修正が中心であり、8.1.8 に既知の重大な脆弱性は報告されていない。数週間程度の運用であれば実務上のリスクは低い。とはいえ、決済プラグインに限らず常に最新バージョンを使うのが基本のため、修正版がリリースされたら速やかに更新する。
手動 ZIP アップロードと管理画面からの自動更新で何が違うのか
一般的には同じ ZIP ファイルを使うため内容に差はないが、自動更新時には WordPress のアップデーターがファイルの置き換えを段階的に行うのに対し、手動アップロードでは一度に全ファイルが上書きされる。キャッシュやオートローダーの生成タイミングの違いが結果に影響している可能性がある。ただし本件では原因が完全に特定されていないため、効果には個体差がある。
PHP バージョンはエラーに関係するか
関係する可能性は高い。PHP 8.0 以降は引数の数の不一致に対して E_ERROR レベルの厳格なエラーを出すが、PHP 7.x では E_WARNING で済んでいたケースもある。Mollie プラグインのシステム要件を確認し、推奨される PHP バージョン(通常 7.4 以上)を使っているかどうかを WooCommerce のステータス画面で確認する。
エラーメールが大量に届いて困っている。どう止めればよいか
WordPress の致命的エラー通知はサイトにアクセスがあるたびに発生するため、更新直後は短時間で大量のメールが届くことがある。最も早い対処は前述のとおり FTP でプラグインフォルダの名前を変更して無効化することだ。メールが止まったら、すぐに 8.1.8 へのロールバックに取りかかる。
他の決済プラグインに切り替えるべきか
このエラーはバージョン 8.1.9 固有の一時的な不具合であり、Mollie プラグイン全体の品質に問題があるわけではない。8.1.8 で問題なく運用できていたのであれば、慌てて乗り換える必要はない。オランダ発の Mollie は欧州で高いシェアを持つ決済プロバイダーであり、プラグインも活発にメンテナンスされている。
この記事のポイント
- Mollie 8.1.9 の致命的エラーはコンストラクタ引数の数が一致しないことが原因
- 最も確実な対処は WP Rollback で 8.1.8 に戻すこと
- 管理画面に入れない場合は FTP でプラグインフォルダをリネームして無効化する
- 手動 ZIP アップロードは回避できる場合とできない場合があり確実性に欠ける
- 修正版が出るまで自動更新を無効にして 8.1.8 のまま運用する

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

Events ManagerでGutenbergのイベントが公開できない時の直し方
Events ManagerをGutenberg編集モードで使っているときに新規イベントが公開できず、クラシックエディタでは問題なく動作する場合、プラグインのバージョンが7.3.1〜7.3.4のいずれかであることが主な原因だ。7.3.5以降へアップデートすると修正される。
どんな操作をしたときに発生するのか

Gutenbergモードを有効にしたEvents Managerで新規イベントを作成する。すべての項目を入力して「公開」ボタンを押しても、画面が再読み込みされステータスが「下書き」のままになり、公開状態に切り替わらない。一方でクラシックエディタに切り替えると、同じ内容でも問題なく公開できるという状況だ。
この現象は、WP標準テーマ(Twenty Twenty-FourやTwenty Twenty-Five)に切り替えても、他のプラグインをすべて無効化しても変わらない。Events Manager側のGutenberg統合部分にバージョン固有の不具合が存在しているために起きる。
公開ボタンが反応しない直接の原因は何か

Events Managerのバージョン7.3.1から7.3.4には、Gutenbergエディタ上でイベントを保存する際に走るバリデーション(検証)処理に問題がある。具体的には、イベントの必須項目が正しく入力されていても内部的な検証に失敗し、「公開」操作が受理されない状態になる。
とくに繰り返しイベント(定期的な開催設定)を扱う場合、「Main recurrence set times are required(メインの繰り返し時刻設定が必要です)」という趣旨の検証エラーが返され、公開をブロックされるケースが報告されている。このバリデーションエラーは管理画面の見た目には表示されず、ブラウザの開発者ツール上で確認できる。
このデモが示すように、エディタの見た目上は正常に操作しているのに、プラグイン内部のAPI応答が原因で公開処理が止まる。Events Manager 7.3.5でこのバリデーション不具合が修正されている。
Events Managerを最新版にアップデートして修正する

最も確実な解決策は、Events Managerをバージョン7.3.5以降にアップデートすることだ。管理画面から数ステップで完了する。
サイトの運用途中でアップデートをためらう場合は、まずステージング環境(テスト用の複製サイト)でアップデート後の動作を確認すると安全だ。近年の国内レンタルサーバーでは、管理パネルからワンクリックでステージング環境を作成できるものも多い。
すぐに公開したい場合の一時的な回避策

プラグインのアップデートが何らかの理由ですぐにできない場合、以下の回避策で公開できることがある。
- 公開ボタンを2回以上連続でクリックする。1回目でいったん下書きとして保存され、2回目以降のクリックで公開状態に切り替わるケースが報告されている。
- イベント編集画面の「Events Manager」設定パネルで、Gutenbergモードを無効にしてクラシックエディタを使う。クラシックエディタでは問題なく公開できる。
これらの回避策は、あくまでアップデート前の応急処置として使う。根本的には7.3.5以降へのアップデートが必要だ。
アップデート後も繰り返しイベントでエラーが出る場合の対処

7.3.5以降でも、繰り返しイベントの設定時にまれに「Main recurrence set times are required(メインの繰り返し時刻設定が必要です)」という趣旨のバリデーションエラーが表示されることがある。このエラーは、繰り返し設定の中核となる日時情報がバリデーションAPIに正しく渡っていない場合に発生する。
まず試すべきは、繰り返し設定を一度クリアして再入力することだ。とくに開始日時と終了日時、および繰り返しパターンの「初回の日時」が空欄になっていないか確認する。カスタムコードでGutenberg有効化を制御していた場合は、そのコードが完全に削除されているかも確認する。残留したコードがAPI通信に干渉している可能性がある。
よくある質問
Events ManagerのGutenbergモードはどこで切り替えられるか
管理画面の「Events」→「設定」→「管理画面」タブにある「イベントエディタの種類」で切り替えられる。ここで「Gutenberg」を選択するとブロックエディタが有効になり、「クラシックエディタ」を選ぶと従来の編集画面に戻る。
Gutenberg有効化のカスタムコードが原因になることはあるか
過去にfunctions.phpなどへ追加したGutenberg有効化コードが削除されずに残っていると、プラグインの設定と競合して予期しない動作を起こす可能性がある。コードが完全に削除されているか、もしくはコメントアウトされているか確認する。
公開ボタンを押しても何も反応しない場合はどうすればよいか
ブラウザの開発者ツール(F12キー)の「コンソール」タブにJavaScriptエラーが表示されていないか確認する。別のプラグインがGutenbergと競合してJavaScriptエラーを起こしている場合、それが原因で公開処理が止まることがある。
クラシックエディタでは問題ないのにGutenbergだけ不具合が出る理由は何か
GutenbergはREST APIを介してデータを保存する仕組みをとっている。Events Managerのバリデーション処理も、GutenbergモードではAPI経由で実行される。クラシックエディタの場合は異なる保存経路を使うため、API側の不具合の影響を受けずに公開できる。
7.3.5はいつリリースされたのか
Events Manager 7.3.5は2026年7月下旬にリリースされ、本件のGutenberg公開不具合が修正されている。管理画面の更新通知から適用できる。
この記事のポイント
- Events Manager 7.3.1〜7.3.4のGutenbergモードには公開できない不具合がある
- 7.3.5以降へアップデートすると修正される
- アップデートできない場合は公開ボタンの複数回クリックやクラシックエディタで一時回避できる
- 繰り返しイベントでの検証エラーは設定の再入力で直ることが多い
- 過去のカスタムコードが競合していないか確認することも大切だ

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

LiteSpeed Cacheでパージ成功してもキャッシュが残る原因と直し方
LiteSpeed Cacheで管理画面やWP-CLIから「Purge All(全キャッシュ削除)」を実行し成功メッセージが出ているにもかかわらず、公開ページがいつまでも古い内容のまま更新されない場合、プラグインのキャッシュ制御と実際に動作しているサーバーレベルのキャッシュ層との間に不整合が起きている可能性が高い。根本的には、LSCacheプラグインの設定最適化と、場合によってはプラグインを一時的に無効化しての強制リフレッシュが有効な解決策になる。
なぜ「全削除」に成功してもキャッシュが残り続けるのか

LiteSpeed Cacheのキャッシュ構造は多層的で、プラグインの管理画面と実際のキャッシュストレージが常に一対一で対応しているとは限らない。管理画面で「Purge All」を実行すると、プラグインは内部的にパージタグを生成し、LSWS(LiteSpeed Web Server)に対してキャッシュ削除の指示を出す。ここで成功メッセージが返ってくるのは、あくまで「指示が出せた」という意味であり、ディスクやメモリ上の実ファイルが完全に消えたことの保証にはならない。
まず試すべきプラグイン側の設定見直し

x-litespeed-cache:hit が返ってくる。x-litespeed-cache-control: no-cache
miss になり、サーバーが動的生成に切り替わった。キャッシュ有効期限とブラウザキャッシュ設定の確認
まず、LSCacheプラグインの「キャッシュ」タブでTTL(Time To Live、キャッシュの有効期限)が極端に長く設定されていないか確認する。デフォルトは604800秒(1週間)だが、公開ページの更新頻度が高いサイトでは3600秒(1時間)程度に短くすることで、パージ操作の効果が出やすくなる。また「ブラウザキャッシュ」タブで、ブラウザ側のキャッシュ保持期間が長すぎると、サーバーのパージ後もユーザーのローカルキャッシュが優先されて古い表示になる。短期間に設定するか、問題切分け中は一時的に無効化(オフ)にする。
オブジェクトキャッシュとRedisの影響を見極める
RedisやMemcachedといった外部オブジェクトキャッシュを使っている環境では、LSCacheがページキャッシュを削除しても、データベースクエリの結果がオブジェクトキャッシュに残り、結果として同じ古い情報でページが再生成される。Redisを使っているなら、管理画面の「LiteSpeed Cache」→「オブジェクトキャッシュ」でステータスを確認し、「Purge Object Cache」を手動で実行する。それでも直らない場合は、問題の切分けとしてredis-cacheやRedis Object Cacheプラグイン自体を一度無効化し、LSCacheだけの状態でパージを試す。
サーバーレベルで強制的にキャッシュを削除する手順
プラグインの操作で改善しない場合、LiteSpeed Web Serverが保持しているキャッシュをOSレベルで手動削除する。特に、LSCacheプラグインが生成したキャッシュ情報と、LSWSの内部キャッシュマップがずれてしまった場合に有効だ。
ディスクキャッシュの格納場所と削除コマンド
SSHでサーバーに接続し、まずLSWSのキャッシュパスを特定する。デフォルトでは /tmp/lshttpd/ または /usr/local/lsws/cachedata/ 以下にキャッシュが格納されている。LSCacheプラグインの「CDN/キャッシュ設定」にある「キャッシュルートパス」を確認すると確実だ。
次に、LSWSを完全に停止する。systemctl restart lsws や管理画面からのグレースフルリスタートではプロセスがクリアされず、内部のキャッシュマップが生き残る。以下の手順で、キャッシュディレクトリを物理的に空にしてから再起動する。
# LSWSを完全停止
/usr/local/lsws/bin/lswsctrl stop
# キャッシュディレクトリとスワップを完全に削除
rm -rf /tmp/lshttpd/swap/*
rm -rf /tmp/lshttpd/cache/*
# LSWSを起動
/usr/local/lsws/bin/lswsctrl start起動後、WordPress管理画面からLSCacheの「Purge All」を実行し、ブラウザのシークレットウィンドウ(または開発者ツールでキャッシュを無効化した状態)で動作を確認する。x-litespeed-cache ヘッダーが miss になっていれば成功だ。
どうしても治らない場合の一時的切り分け
上記の手順を実行しても、ベアURL(パラメータなしの通常アクセス)だけが古いキャッシュを返し続ける場合、LSCacheプラグイン自体がリクエスト段階でキャッシュの再取得を意図せず阻害している可能性が高い。この状況は、特定の条件下でLSCacheプラグインがブラウザやリバースプロキシに強力なCache-Controlヘッダーを設定し、サーバー側でミスになってもCDNやブラウザが古いデータを返し続けるケースだ。
最終的な切分けとして、LSCacheプラグインを5分〜10分間だけ完全に無効化する。無効化後に即座にキャッシュが更新されるなら、LSCacheプラグインの内部ロジックまたは設定が主因であると特定できる。プラグインを再有効化した後、デフォルト設定へのリセットや、問題を再現させた設定項目を一つずつ絞り込む。
よくある質問
クエリ文字列を付けるとキャッシュがバイパスされる理由は?
LiteSpeed Cacheは、URLにパラメータ(?=xxx)が付与されたリクエストを、デフォルトでキャッシュ対象外とみなす。そのためベアURLでは x-litespeed-cache:hit で古いキャッシュが返っているのに、/?v=2 のような文字列を付けると miss となり、動的に生成された最新ページが表示される。
サーバーを再起動できない共有サーバーではどう対処すればよいか
多くの共用サーバーではSSHやLSWSの制御権限が制限されている。この場合、LSCacheプラグインの「ツールボックス」→「Purge All」を実行し、即座にプラグインを無効化する。その後「LiteSpeed Cache」を再有効化し、デフォルト設定へのリセットを試す。サーバー側のキャッシュディレクトリに触れない環境では、この手順が最も確実な強制リセットになる。
パージ後のキャッシュ再生成を防ぎたい場合の設定は?
公開前のプレビューや検証でキャッシュを完全に止めたい場合、LSCacheプラグインの「キャッシュ」→「キャッシュを有効化」のトグルを一時的にオフにする方法が最も確実だ。ただしこの設定はサイト全体のパフォーマンスに影響するため、検証後は必ずオンに戻し、特定のページだけ除外したい場合は「URI 除外」機能を使う。
この記事のポイント
- LSCacheのパージ成功表示が実キャッシュ削除の保証にはならない
- サーバーレベルでディスクキャッシュを直接削除すると治るケースが多い
- Redisなどの外部オブジェクトキャッシュも同時に削除する必要がある
- クエリ文字列でバイパスされる現象はLSCacheの正常動作だが、ベアURLが古いのは異常
- どうしても治らなければ、プラグインの一時無効化で原因をLSCacheに特定できる

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

WordPress wp2shell攻撃後の完全クリーンアップと再発防止手順
WordPress が REST Batch API を悪用した wp2shell 攻撃を受け、Web シェルを仕込まれたり偽の管理者を作られたりした場合は、WordPress 本体の更新だけでなくファイルとデータベースの完全な掃除が必要になる。攻撃者は認証なしでコードを実行できるため、必ず FTP/SSH と SQL の両面から対処する。
この攻撃は SQL インジェクションで PHP ファイルをサーバーに直接書き込み、データベース内にも偽のメニュー項目や changeset を残す。パッチを当てただけではバックドアが生き残り、再侵入される危険がある。
上図は攻撃直後と完全クリーンアップ後の違いだ。この記事ではファイル・データベース・ユーザー管理の3層で掃除し、再発を防ぐまでの手順を詳しく解説する。
wp2shell 攻撃で何が起きているのか

WordPress の REST Batch API は複数の REST API リクエストをまとめて送信できる機能だ。この脆弱性を突かれると、認証なしで SQL インジェクションを起こし、INTO OUTFILE 命令で PHP ファイルをサーバーに書き込める。書き込まれた PHP ファイルは Web シェルとして機能し、攻撃者が自由にコマンドを実行できるようになる。
さらに攻撃者はデータベースに直接アクセスできるため、パスワードのハッシュを盗んだり、自分自身に管理者権限を付与したりすることが可能だ。偽のプラグインを /wp-content/mu-plugins/ に仕込んで恒久的なバックドアにする手口も確認されている。
被害にあったサイトを完全に掃除する手順

掃除は「ファイルの掃除」「ユーザーとセッションの掃除」「データベースの掃除」の3段階で進める。始める前に必ずファイルとデータベースの完全バックアップを取る。
ファイルシステムから Web シェルと偽プラグインを削除する
FTP クライアントや SSH でサーバーに接続し、まず /wp-content/cache/ ディレクトリを開く。キャッシュ系のディレクトリ(/cache/ や /wpo-cache/ など)に不自然な英数字の羅列(e042u9xy9ra1.php のようなファイル名)があれば、それが Web シェルだ。すべて削除する。
次に /wp-content/mu-plugins/ を確認する。Must-Use プラグインは自動的に有効化されるため、攻撃者が好んで使う場所だ。身に覚えのないファイル(galex_patch.php など)があれば削除する。通常の /wp-content/plugins/ にも見慣れないプラグインが追加されていないか調べる。
ファイルの掃除が終わったら、WordPress 本体をパッチ適用済みバージョン(6.9.5 または 7.0.2 以上)に更新する。この更新で Batch API の脆弱性自体が塞がる。
wp-config.php にファイル改変防止の定数を追加する
将来の攻撃に備え、管理画面からのファイル編集とプラグインのインストールを無効化する。FTP または SSH で wp-config.php を開き、以下の2行を追記する。
define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true );DISALLOW_FILE_EDIT は管理画面の「テーマエディター」「プラグインエディター」を無効化する。DISALLOW_FILE_MODS は管理画面からのプラグイン追加や更新をブロックする。すでに侵入された後の対策ではなく、掃除が完了した後に再発を防ぐ設定だ。
ユーザーとパスワード、セッションの掃除

攻撃者はデータベースに直接アクセスしていたため、パスワードのハッシュを抜き取った可能性が高い。管理者を含む全ユーザーのパスワードを変更する。WordPress 管理画面だけでなく、MySQL データベース自体のパスワードも変更し、wp-config.php の DB_PASSWORD を新しいものに書き換える。
パスワード変更だけでは不十分だ。攻撃者がまだログインしたままかもしれない。全セッションを強制的に切断するには、Salt Keys(ソルトキー)を再生成して wp-config.php に上書きする。WordPress 公式の Salt Keys ジェネレーターで新しいキーセットを取得し、既存のキーと置き換えれば全デバイスのログイン状態が即座に無効になる。
最後に、管理画面の「ユーザー」一覧を開き、見覚えのない管理者アカウントが作られていないか確認する。もし存在すれば即座に削除する。
データベースに残った偽のレコードを削除する

wp2shell 攻撃は、WordPress のセキュリティフィルターをすり抜けるために、データベース上に偽のナビゲーションメニュー項目と changeset(カスタマイザーの変更履歴)を一時的に生成する。これらのレコードは post_date が 2020-01-01 00:00:00 に固定されており、URL ペイロードに example.invalid を含むという特徴がある。
以下の SQL を phpMyAdmin などで実行する。なお、接頭辞(プレフィックス)がデフォルトの wp_ ではない場合は、コード内の wp_ を実際のプレフィックス(例: wp2_ や mysite_)に置き換える必要がある。
偽の changeset を削除する
DELETE FROM wp_posts WHERE post_type = 'customize_changeset' AND post_date = '2020-01-01 00:00:00';偽のナビゲーションメニュー項目を削除する
DELETE FROM wp_posts WHERE post_type = 'nav_menu_item' AND post_date = '2020-01-01 00:00:00';悪意のあるメタデータを削除する
DELETE FROM wp_postmeta WHERE meta_value LIKE '%example.invalid%';これらのクエリでデータベース上の痕跡を一掃できる。実行前には必ずデータベースのバックアップを取る。
データベースユーザーから FILE 権限を剥奪する

今回の攻撃は SQL インジェクション経由で INTO OUTFILE 命令を使い、データベースからディスクにファイルを書き込んでいた。WordPress の通常動作に FILE 権限はまったく不要だ。この権限を WordPress のデータベースユーザーから剥奪しておけば、同種の攻撃が再び成功する可能性を大きく下げられる。
データベースに root 権限でログインし、以下の SQL を実行する。'wp_user_name'@'localhost' は実際の WordPress 用データベースユーザー名に置き換える。
REVOKE FILE ON *.* FROM 'wp_user_name'@'localhost';
FLUSH PRIVILEGES;REVOKE FILE は FILE 権限を取り消し、FLUSH PRIVILEGES は変更を即時反映する。これでデータベースからファイルシステムへの書き込み経路が遮断される。
よくある質問
WordPress を更新しただけで掃除は不要か
更新だけでは不十分だ。攻撃者はすでに Web シェルをサーバーに書き込んでおり、そのファイルは更新では削除されない。データベース内の偽レコードや不正な管理者アカウントも残ったままになる。必ずファイルとデータベースの両方を掃除する。
DISALLOW_FILE_MODS を設定すると管理画面からプラグインを追加できなくなるのか
そのとおりだ。DISALLOW_FILE_MODS を true にすると、管理画面からのプラグインのインストール・更新・削除、テーマのインストール・更新がすべてブロックされる。必要な更新は FTP や SSH 経由で手動で行う運用になるが、攻撃者が管理画面からファイルを改変する経路を完全に塞げる。
SQL クエリのプレフィックス wp_ を変更し忘れるとどうなるか
テーブルが存在しないというエラーが出るだけで、データが破壊されることはない。それでも、間違ったテーブルを操作しないよう実行前に必ず実際のプレフィックスを確認する。多くのレンタルサーバーではインストール時に自動生成された固有のプレフィックスが使われている。
FILE 権限を剥奪すると WordPress の動作に影響は出るか
WordPress の通常動作に FILE 権限は一切使われない。記事の投稿やプラグインの動作、データベースの読み書きに影響は出ないため、安全に剥奪できる。
この記事のポイント
- WordPress 本体の更新だけではバックドアとデータベースの痕跡が残る
- /wp-content/cache/ と /wp-content/mu-plugins/ の不審な PHP ファイルを削除する
- 全ユーザーのパスワード変更と Salt Keys 再生成でセッションを強制切断する
- データベースから post_date が 2020-01-01 の偽 changeset とメニュー項目を削除する
- WordPress の DB ユーザーから FILE 権限を剥奪し INTO OUTFILE 経路を塞ぐ

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

WooCommerceバリエーション商品のカート追加で重大エラーが出る時の修正方法
WooCommerce のブロックベースカートでバリエーション商品を追加した際に「woo-min-max-quantity-step-control-single」プラグインが原因で「このサイトで重大なエラーが発生しました」と表示される場合、原因はプラグインが商品オブジェクトの取得失敗を考慮していないことだ。該当ファイルの PHP コードに数行の修正を加えればエラーを回避できる。
なぜブロックカートでバリエーション商品だけエラーになるのか
エラーログを確認すると、問題はプラグインの min-max-controller.php 872行目付近で発生している。この行では wc_get_product() で商品情報を取得した直後に ->get_id() を呼んでいるが、wc_get_product() は対象の商品が見つからなかった場合に false を返す。ブロックベースのカート(Store API)経由でバリエーション商品が追加されると、この関数がまれに false を返す状況が発生する。プラグインのコードはその可能性をまったく想定しておらず、結果として「Call to a member function get_id() on false」という致命的な PHP エラーに直結している。
エラーを根本解決するためのコード修正手順

false チェックを追加する該当ファイルを開き 872 行目周辺を特定する
FTP クライアント、またはレンタルサーバーのファイルマネージャーで、以下のパスにあるファイルを開く。WordPress 管理画面の「プラグイン」→「プラグインファイルエディター」から編集するのはできるだけ避ける。エディター画面で編集ミスをするとサイト全体が停止するリスクがあるためだ。
/wp-content/plugins/woo-min-max-quantity-step-control-single/includes/min-max-controller.php
使用しているエディタで行番号表示を有効にし、872 行目付近まで移動する。エラーログに表示されているとおり、->get_id() を直接呼んでいる箇所を探そう。
修正前と修正後のコードを比較する
$min = $product->get_id();
if ( ! $product || ! is_a( $product, ‘WC_Product’ ) ) {
return;
}
$min = $product->get_id();
PHP コード修正の内容と意味
修正の核心は、$product が有効なオブジェクトかどうかを事前に検証することだ。
! $product は wc_get_product() が false を返した場合を検出する。is_a( $product, 'WC_Product' ) は、取得できたとしてもそれが WooCommerce の正規の商品オブジェクトであることを確認する。どちらかの条件を満たさなければ return で処理を中断し、以降の ->get_id() が呼ばれないようにする仕組みだ。
このガード節を入れることで、ブロックカート経由でどういった商品情報が渡ってきても、致命的なエラーにはならなくなる。
修正してもエラーが直らない場合の確認点
まれに、修正だけでは根本解決しないケースがある。以下の点も確認してみてほしい。
WooCommerce データベースのクリーンアップを実行する
「WooCommerce」→「ステータス」→「ツール」タブに移動し、「WooCommerce トランジェントをクリア」と「期限切れのトランジェントを削除」を実行する。キャッシュが原因で商品情報が正しく取得できていない場合に効果がある。
最小最大数量プラグインのバージョンと WooCommerce のバージョンを確認する
プラグインが最新の WooCommerce や Store API に対応していない可能性がある。プラグインの公式ページで対応バージョンを確認し、場合によっては別の数量制御プラグインを検討する必要がある。修正を加えても根本的な設計の問題で他の不具合が発生する場合は、開発者に修正リクエストを送りつつ、一時的に従来のショートコードカート([woocommerce_cart])へ切り戻すことも視野に入れる。
よくある質問
この問題はブロックカートだけに発生するのか
主にブロックベースのカートとチェックアウト(Store API)で発生する。従来のショートコードカートではエラーが出ないことも多いが、プラグインコードに潜在的な問題があるため、修正しておく方が安全だ。
プラグインがアップデートされたら修正は消えるか
消える。今回の修正はプラグインのコアファイルを直接編集しているため、プラグインにアップデートが配信されると編集内容は上書きされる。アップデート後に同様のエラーが再発した場合は、再び同じ手順で修正するか、開発者が修正を取り込むまでアップデートを控える必要がある。
子テーマの functions.php でこのエラーを回避できるか
難しい。今回のエラーはプラグイン内部の特定の行で発生しており、かつ商品取得のロジック周辺にフックが用意されていない限り、テーマファイル側から割り込んで防御することはできない。直接ファイルを編集する今回の方法が最も確実な対処法になる。
修正中にサイトが壊れてしまった場合の直し方は
FTP でサーバーにアクセスし、修正前にバックアップしておいた min-max-controller.php を上書きアップロードする。バックアップがない場合は、プラグインを一度削除して再インストールするのが早い。ただし、プラグインの設定内容はあらかじめメモしておく必要がある。
この記事のポイント
- エラー原因はプラグイン内での
get_id()呼び出し前にfalseチェックがないこと - 修正対象は
min-max-controller.phpの 872 行目付近 wc_get_product()がfalseを返す状況を考慮したガード節を追加する- ブロックカート(Store API)利用時に特に発生しやすい PHP エラーへの対処法
- 直接ファイルを修正するため、プラグインのアップデートで編集が上書きされる点に注意

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

WordPressカスタムHTMLブロックが編集画面で消える原因と直し方
WordPress のブロックエディターでカスタム HTML ブロックを保存後に編集画面を開き直すと、ブロックの中身がまるごと消えて空欄に見える現象は、Gutenberg の React 側パーサーが HTML 構造を正しく解析できずに描画を放棄しているのが主な原因だ。script タグや閉じタグのない要素、複雑なインラインスタイルなどが引き金になる。
なぜカスタムHTMLブロックが編集画面で空になるのか

フロントエンドでは正しく表示されるのに、管理画面のブロックエディターだけで中身が空になるのは、データそのものはデータベースに保存されている証拠だ。コードエディターモードに切り替えれば、貼り付けた HTML が消えずに残っているのが確認できる。この現象が起こるのは、ブロックエディターがビジュアルモードでブロック内容を再表示するときに、DOM パーサーが特定の HTML を「壊れた構造」と判断してレンダリングを飛ばしてしまうからだ。
具体的には、Gutenberg が内部的に使用している React の DOM レンダリング機構が、管理画面の安全な枠組みの中で処理できないタグや構文に遭遇すると、そのブロック全体を安全のためにスキップする。結果として視覚的には空のブロックに見えるが、データベースの post_content には元のコードがそのまま格納されている。
カスタムHTMLブロックの中身が消える原因を特定する手順

まず、どの部分が問題を引き起こしているのかを切り分ける。以下の手順で原因箇所を絞り込む。
ブロックエディターのコードエディターモードで現状を確認する
編集画面右上の「︙」メニューから「コードエディター」を選択すると、ビジュアル表示ではなく生の HTML 構造が表示される。カスタムHTMLブロック内のコードがここで確認できれば、データは失われていない。このとき、Markdown 記法でブロック境界を示す <!-- wp:html --> と <!-- /wp:html --> のコメント行の内側にコードが残っているかを確かめる。
HTMLを最小単位に分解して原因のタグを特定する
ブロックに貼り付けた HTML を、1つのタグ単位で分割してカスタムHTMLブロックに1つずつ入れ直す。たとえば script タグ、style タグ、空要素(<div></div> など)、インラインイベントハンドラ(onclick など)をそれぞれ別のブロックに分けて保存し、再読み込み時に消えるかどうかをテストする。問題を起こすタグが特定できれば、その部分だけ別の実装方法に切り替えられる。
プラグイン競合の可能性を調べる
特定のプラグインがブロックエディターの動作に干渉して、カスタムHTMLブロックの描画を阻害しているケースもある。特にエディター拡張系のプラグインや、セキュリティ目的でスクリプトをフィルタリングするプラグインが入っている場合は、すべてのプラグインを一度無効化して標準テーマに切り替え、問題が再現するか確認する。プラグインが原因であれば、1つずつ再有効化して犯人を特定する。
カスタムHTMLブロックを正常に表示させる具体的な修正手順

原因が特定できたら、次は実際にブロックを正常に表示させる。script タグや複雑な HTML 構造が原因だった場合、以下のアプローチで回避できる。
script タグや iframe はカスタムHTMLブロックではなく適切な場所に配置する
Gutenberg のカスタムHTMLブロックは、セキュリティ上の理由から script タグの実行を制限している。また、ビジュアルエディターでの再レンダリング時に script タグを含むブロックを空として扱う挙動が確認されている。JavaScript を埋め込みたい場合は、カスタムHTMLブロックではなく、functions.php に wp_enqueue_script で登録するか、専用のコード埋め込みプラグインを使う。iframe も同様に、エディターのプレビューで空白になることがあるため、フロントエンドのみで描画される仕組みを検討する。
閉じタグのない空要素を見直す
カスタムHTMLブロックに <div></div> のような中身のない空タグや、閉じタグを省略した要素が含まれていると、Gutenberg のブロックパーサーが構造を正しく解釈できずにブロック全体をスキップすることがある。空の div や span は削除するか、 を入れて実体を持たせる。とくに WordPress の自動整形機能(wpautop)が余分な p タグや br タグを挿入することで、意図しない空要素が生まれることもある。
複雑なHTML構造はカスタムフィールドやショートコードに置き換える
テーブルやフォーム、装飾を多用したマークアップは、カスタムHTMLブロック1つにまとめるよりも、ACF(Advanced Custom Fields)のテキストエリアフィールドや、ショートコード化して出力する方が安定する。とくにクライアントが自分で編集する前提のサイトでは、カスタムHTMLブロックを直接触らせると今回のようなトラブルが再発しやすい。テーマ側でテンプレートパーツとして管理し、投稿画面では入力欄だけを提供する設計が安全だ。
今後同様のトラブルを防ぐための運用ポイント

カスタムHTMLブロックに貼り付ける前にコード検証を行う
外部の HTML スニペットをそのまま貼り付ける前に、W3C のバリデーターや VSCode の構文チェック機能でタグの閉じ忘れや文法エラーがないかを確認する。コピー元の Web ページから取得したコードには、不要な属性や非推奨のタグが混じっていることが多い。貼り付け前に一度テキストエディターにペーストし、明らかな問題を取り除いてからブロックに入力する習慣をつける。
WordPress と Gutenberg を最新バージョンに保つ
Gutenberg プラグインを単体でインストールしている場合は、定期的に更新することでブロックパーサーの改善や既知の不具合修正が適用される。コア組み込みのブロックエディターであっても、WordPress 本体のアップデートによってパースエンジンの挙動が改良されることがある。編集画面でカスタムHTMLブロックが空になる現象の一部は、過去のバージョンで修正されたバグに起因している可能性もあるため、まずは最新の状態であることを確認する。
どうしても必要な場合はコードエディターモードを常用する
ビジュアルエディターで空になってしまう HTML をどうしてもページに残したいときは、編集時にコードエディターモードに切り替えて作業する方法が最終的な回避策になる。データベースにコードが正しく保存されているなら、コードエディター表示では常に中身が確認できる。手間は増えるが、複雑なマークアップや埋め込みコードを扱うページでは、あらかじめこの運用を前提にしておくとトラブルが起きても編集が止まらない。
よくある質問
カスタムHTMLブロックの中身は完全に消えたのか
ビジュアルエディターでは空に見えても、コードエディターモードに切り替えると HTML が残っていることがほとんどだ。データベースの post_content にも保存されているため、失われたわけではない。
プラグインをすべて無効化しても直らない場合はどうすればいいか
テーマの functions.php や使用中の子テーマがエディターの動作に干渉している可能性がある。標準テーマ(Twenty Twenty-Five など)に一時的に切り替えて再現するか確認し、テーマ側のフィルターやアクションを調査する。
script タグをカスタムHTMLブロックで使う正しい方法はあるか
原則としてカスタムHTMLブロック内の script タグは推奨されない。管理画面でのレンダリング問題に加え、セキュリティプラグインやサーバー側のフィルターで除去されるリスクもある。どうしても必要な場合はショートコード化するか、wp_enqueue_script でテーマに登録するのが安全だ。
ビジュアルエディターで空白になる特定の HTML タグの一覧はあるか
公式の一覧は存在しないが、script タグ、style タグ、iframe、object、embed、空の div や span、コメントアウト行、複雑に入れ子になったインラインスタイル付き要素などが報告されている。問題が起きたら該当タグを一つずつ検証するのが確実だ。
ビジュアルエディターで空になる現象は Gutenberg のバグなのか
仕様とバグの両面がある。script タグの実行制限はセキュリティ上の意図的な制限であり、空要素のパース失敗はブロックエディターの改善が期待される領域だ。WordPress コアのバージョンアップによって挙動が変わることもあるため、最新バージョンへの更新が有効な場合が多い。
この記事のポイント
- カスタムHTMLブロックが空に見えてもデータはデータベースに残っている
- script タグや空要素、閉じタグ省略がパース失敗の主原因
- コードエディターモードで中身を確認し原因タグを特定する
- 複雑な HTML はカスタムフィールドやショートコードで管理する
- WordPress と Gutenberg の最新化で改善するケースがある

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

ハッキングされたWordPressサイトの完全復旧手順と再発防止策
ハッキングされた WordPress サイトを復旧するには、マルウェアの削除だけでは不十分であり、SFTP や SSH といったホスティングレベルの認証情報をすべてローテーションし、バックドアを残さず完全に除去した上で、数週間にわたって再感染していないか監視を続ける必要がある。
WordPress がハッキングされる主な原因はどこにあるのか

侵入経路として圧倒的に多いのが、更新されていないプラグインやテーマの脆弱性だ。Patchstack の統計では、WordPress エコシステム全体の脆弱性の約96%がプラグイン、残り4%がテーマに存在し、コア本体に起因するものはごくわずかである。脆弱性が公表され修正パッチがリリースされると、攻撃者は数時間以内にそのバージョンを標的としたスキャンを開始する。
もう一つの主な侵入口は、弱いパスワードや使い回しの認証情報、あるいはフィッシング詐欺などで盗まれたログイン情報だ。攻撃者は WordPress の管理画面だけでなく、SFTP や SSH、ホスティングコントロールパネルといった上位のアクセス権も狙う。
侵入に成功した攻撃者は、すぐに目立った改ざんを行うとは限らない。ファイルに巧妙に偽装したバックドアを仕込み、追加の管理者アカウントを作成した後、数週間から数カ月潜伏するケースが一般的だ。そのため、サイト改ざんの直前に取得したバックアップであっても、見えないバックドアがすでに仕込まれている可能性を前提に復旧作業を進めなければならない。
上図の流れが示すとおり、攻撃者はサイトに侵入したあと長期間潜伏し、ファイルやデータベースの奥深くに復旧を妨げる仕掛けを残す。
完全な掃除と再発防止のための5ステップ

証拠を保全しログを収集する
復旧作業に着手する前に、改ざんされた状態のサイト全体(全ファイルとデータベースダンプ)のバックアップを取得し、証拠として安全な場所に保管する。ログの収集も同時に行う。利用しているサーバー会社へ、ウェブアクセスログ、SSH ログ、SFTP ログを依頼する。ログの保存期間はサーバー会社によって異なり、ウェブアクセスログは48時間程度、SFTP ログは提供されない場合もあるため、できるだけ早く依頼する必要がある。
解析ツールを使って感染範囲を特定する
取得したバックアップとログを解析する。AI を活用した解析ツールを使うと、大量のファイルからパターンを検出しやすい。もし感染前のクリーンなバックアップが存在するなら、それと比較することで未知のバックドアの発見率が大幅に上がる。スキャン範囲は wp-content ディレクトリ内だけに限定せず、ドキュメントルート全体とし、フォントファイルやキャッシュディレクトリに偽装されたシェルスクリプトも見落とさないようにする。
見つかったマルウェアと不正アカウントを削除する
検出された悪意のあるファイルは無効化ではなく削除する。単にプラグインを無効化しただけでは、該当ファイルに直接 URL でアクセスされると動作してしまう。また、管理画面のユーザー一覧に表示されない管理者アカウントや、データベースに直接埋め込まれた不正なエントリも除去する。
すべての認証情報をローテーションする
ファイルの掃除が完了しても、認証情報が漏洩したままだと再感染を繰り返す。WordPress のソルト(暗号化用の乱数文字列)とデータベースのパスワードを変更し、全ユーザーのパスワードをリセットする。さらに、SFTP のパスワード、SSH の公開鍵(身に覚えのない鍵はすべて削除)、API トークン、ホスティングのコントロールパネルのパスワードもすべて変更し、多要素認証を有効にする。作業に関わった全員が、自分のパソコンをマルウェアスキャンし、FTP クライアントにパスワードを保存する習慣をやめることも忘れてはならない。
この三層すべてで認証情報を更新しない限り、攻撃者は残った認証情報を使って何度でも侵入できる。
再感染の有無を監視し、クリーンな状態を維持する
一度の掃除で完全に除去できたと判断してはならない。掃除中に攻撃者が再侵入している可能性もあるため、作業が完了したら新しいバックアップとログを取得し、最初の解析ステップから再度実行する。このサイクルを、少なくとも二回連続で異常が検出されなくなるまで繰り返す。
本当にクリーンだと確信できるバックアップが取得できたら、それを信頼できるソース・オブ・トゥルース(基準点)として保管する。その後の定期バックアップはすべてこの基準点と比較し、差分が発生した瞬間を検知できるようにする。サイトが改ざんされる前に異常を捉えるには、復旧後も数週間は毎日バックアップとスキャンを継続し、問題がなければ監視頻度を徐々に落としていく方法が現実的だ。
アクセス権限を「必要性」で見直す

WordPress の管理者アカウント、SFTP ユーザー、SSH 鍵、ホスティングのコントロールパネルユーザーは、それぞれが攻撃者にとっての侵入口になり得る。信頼できる人物であっても、その人が使うパソコンがマルウェアに感染したり、パスワードがフィッシング詐欺で盗まれたりすれば、そのアカウントは攻撃者に利用される。
そのため、アクセス権限は「信頼」ではなく「業務上の必要性」だけを基準に付与する。サイトの編集者に管理者権限は必要ないし、たまにコンテンツを修正するだけの担当者に SFTP アカウントは不要だ。経営者であっても、サーバーの操作が業務に含まれないならば管理者アクセスを持つべきではない。権限を持つアカウントの数を最小限に減らし、それぞれの権限レベルも必要最低限に絞ることが、最も低コストで効果的な防御策となる。
上記のように、権限を必要最低限に絞り込むだけで、攻撃者が悪用できる認証情報の総数は大幅に減る。
よくある質問
バックドアはどこに隠れていることが多いのか
wp-content 内のプラグインやテーマだけではなく、ドキュメントルート直下や、画像アップロードディレクトリ、キャッシュフォルダなどに偽装されるケースが多い。フォントファイル(.woff や .ttf)に偽装した悪意ある PHP コードが埋め込まれている事例もある。スキャンは必ずサイトのルート全体を対象にする必要がある。
データベースにもバックドアは残るのか
残る。管理画面のユーザー一覧に表示されない管理者アカウントや、プラグイン一覧から隠蔽された悪意あるプラグインのエントリがデータベースに直接書き込まれていることがある。ファイルの掃除だけでなく、データベースの直接確認も必須だ。
無料のセキュリティプラグインだけで復旧できるのか
セキュリティプラグインは感染の検知や予防には有効だが、すでに深く侵入されたサイトの完全な復旧を保証するものではない。特にホスティングレベルの認証情報が漏洩している場合、プラグインのスキャンでは検出できない経路から再侵入される。認証情報のローテーションと継続的なスキャンの組み合わせが不可欠になる。
復旧後、いつまで監視を続ければよいのか
少なくとも2週間は毎日のバックアップとスキャンを継続するのが現実的な目安だ。攻撃者が盗んだ認証情報をしばらく寝かせてから使うケースもあるため、数日間問題がなかったというだけで監視をやめてはいけない。2週間以上経過し、その間の全スキャンで異常がなければ、監視頻度を週に数回へ徐々に落としてもよい。
WP CLI を使わずに復旧作業は可能か
可能だが、手作業でのファイルの確認やデータベースの直接操作が必要になるため、作業時間と見落としのリスクが増加する。WP CLI に抵抗がある場合は、信頼できるエンジニアに依頼する方が安全だ。サーバー会社によっては、マルウェアスキャンと駆除の有償サービスを提供しているところもある。
この記事のポイント
- ハッキングの侵入経路はプラグインやテーマの脆弱性、および漏洩した認証情報が大半を占める
- バックドアはファイルとデータベースの両方に潜伏し、直近のバックアップも汚染されている前提で作業する
- 復旧にはファイル削除と同時に、WordPress、ホスティング、作業端末の三層で認証情報のローテーションが必須
- アクセス権限は「信頼」ではなく「必要性」で付与し、不要なアカウントは即座に削除する
- 一度の掃除で完了とせず、数週間の継続監視と複数回のスキャンで再感染の有無を確認する

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

WooCommerce Taxが配送先住所を無視する原因と修正手順
WooCommerceの自動税計算(WooCommerce Tax)が配送先住所を無視して店舗住所の税率を適用し続ける場合、設定のキャッシュか配送先住所の認識不良が原因だ。税計算の基準を再確認し、プラグインのトランジェントデータを手動で削除すれば、多くのケースで正しい税率に戻る。
配送先住所ではなく店舗住所の税率が使われる原因

WooCommerce Tax(旧称 WooCommerce Shipping & Tax)は、有効化すると TaxJar の自動税率データベースを参照して税額を算出する。管理画面の「WooCommerce > 設定 > 税」で「顧客の配送先住所に基づいて計算する」を選択しているにもかかわらず店舗住所の税率が使われるのは、次のいずれかが起きていると考えられる。
- 税計算の基準設定が実際には店舗住所のまま保存されていない、または別のフィルターで上書きされている
- プラグインが内部に保持するトランジェントキャッシュが古い設定を返し、配送先住所を無視している
- チェックアウト時に配送先住所が正しくシステムに渡っていない(テーマや他のプラグインによる競合)
- WooCommerce Tax が店舗の税ネクサス(課税拠点)を元にした「オリジンベース課税」のルールを配送先住所より優先してしまっている
特に最後の点は、米国のように州ごとにオリジンベース/デスティネーションベースの課税方式が異なる地域で混乱しやすい。日本国内のオンラインショップでは基本的に配送先住所の税率(消費税10%または軽減税率8%)が使われるべきだが、WooCommerce Tax が海外の課税ロジックを引きずっている場合もあり、実際に「店舗住所を変えると税率が変わってしまう」といった現象が報告されている。
配送先住所「大阪市 530-0001」(税率8.25%のはず)
↓
適用される税率 → 店舗住所「東京都 100-0001」の税率10%
配送先住所「大阪市 530-0001」
↓
適用される税率 → 配送先住所の8.25%
このデモのように、配送先住所を正しく入力していても、店舗住所の税率だけが繰り返し使われるのが典型的な症状だ。
税計算の基準が本当に配送先住所になっているか再確認する

まず根本的な設定ミスがないか、管理画面をチェックする。
設定画面上は正しく見えていても、内部的に値がロックされている場合がある。STEP 3 のように一度無効化して再保存することで、WooCommerce Tax の内部キャッシュをリセットできる。
トランジェントキャッシュを手動で削除する
WooCommerce Tax は API から取得した税率データを WordPress のトランジェント(一時キャッシュ)に保存している。このキャッシュが古いままだと、配送先住所が変わっても最初に引いた店舗住所のレートを返し続けることがある。
データベースを直接操作せずにキャッシュをクリアする方法
- WooCommerce > ステータス > ツール に移動する
- 「WooCommerce トランジェントをクリア」を実行する
- さらに「顧客セッションをクリア」も実施する
- 必要に応じて、WooCommerce Tax プラグインを無効化してから削除し、再度インストールして有効化する
再インストール時には、プラグインが新しい API キーを取得し、税設定が初期化される。その後、必ず「WooCommerce > 設定 > 税」で「配送先住所に基づいて計算する」を再設定する。
配送先住所の受け渡しをデバッグモードで検証する

テーマや他のプラグインの影響で、チェックアウト画面から正しい配送先住所が WooCommerce Tax に渡っていない可能性もある。WooCommerce のデバッグモードを有効にして、税計算の内部ログを確認する。
define('WP_DEBUG', true); を追加WooCommerce > ステータス > ログ に、woocommerce-tax や taxjar のログファイルが生成される。配送先住所ではなく店舗住所が送信されているようであれば、テーマの functions.php やカスタムコードが住所情報を改変していないか精査する。
応急的に店舗住所を「配送先住所」と同じ扱いにするフィルター
どうしても自動税計算が配送先住所を認識せず、緊急で正しい税率を適用しなければならない場合、WordPress のフィルターフックを使って一時的に配送先住所を強制的に税計算に使わせることもできる。
add_filter( 'woocommerce_tax_based_on', function( $base ) {
if ( is_checkout() || is_cart() ) {
return 'shipping';
}
return $base;
});このコードを子テーマの functions.php に追加すれば、カート・チェックアウト画面では常に配送先住所ベースの計算が強制される。ただし、根本原因の解決にはならないため、あくまで応急策として利用する。
よくある質問

WooCommerce Tax を再インストールしても直らないのはなぜか
再インストールだけでは、データベースに残ったトランジェントや設定値が削除されないことがある。プラグインを削除した後に「WooCommerce > ステータス > ツール」からトランジェントを完全クリアし、その上で再インストールする必要がある。
配送先住所が正しく入力されているのに税率が変わらないのはどうしてか
WooCommerce Tax は TaxJar API に配送先の ZIP コードと国・州の情報を送り、税率を取得する。このとき、ZIP コードが実在しないか API が認識できない場合、フォールバックとして店舗住所の税率を返す仕様がある。テストする住所が実在するか、郵便番号のフォーマットが正しいかを再確認する。
WooCommerce Tax を使わずに日本国内の税率を正確に計算するにはどうすればよいか
日本国内のオンラインショップで消費税のみを扱うなら、自動税率プラグインを無効化し、WooCommerce 標準の税率設定で「標準税率(10%)」と「軽減税率(8%)」を手動で登録する方が安定する。配送先住所の県や市町村による税率差分が不要なケースが大半のため、あえて自動計算を導入する必要はない。
テスト注文を何度も行っても税額が変わらない場合の最終確認事項は
テスト注文時には、必ずブラウザのシークレットウィンドウを使い、サイトのキャッシュやセッションの影響を排除する。また、カートの計算がセッション情報に依存するため、住所を変えるたびにカートを空にしてから再度商品を追加する。
特定の州や地域でオリジンベース課税のせいで税率が店舗住所になることはあるのか
米国の一部の州では、店舗所在地と配送先の両方が同じ州内にある場合、店舗所在地の税率を適用するオリジンベース課税が採用されている。しかし、WooCommerce Tax は州ごとの課税方式を自動で判別するわけではなく、設定上のトラブルでこの現象が起こることがある。日本のショップでは関係ないが、海外向けに販売する場合は注意が必要だ。
この記事のポイント
- 自動税計算が配送先住所を無視するのは、設定キャッシュか住所の受け渡し不良が主な原因
- 「WooCommerce > 設定 > 税」の計算基準を再確認し、無効化→再有効化で内部リセットを試す
- トランジェントキャッシュを手動クリアし、必要ならプラグインの再インストールを行う
- デバッグログで TaxJar API へのリクエスト内容を検証する
- 日本国内のみのショップなら自動税率をやめ、標準税率を手動設定する方が安定する

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

Booking Calendar更新後にサイトが壊れた時の原因と直し方
Booking Calendar プラグインを 11.4.1 から 11.4.2 へ更新した直後にサイトが壊れた場合、無料版(Booking Calendar)と有料版(Booking Calendar Pro または Booking Manager)のバージョン不一致が主要因だ。手動で両方を同一の最新バージョンに揃え、かつ Pro 版のライセンスを再適用すれば復旧できる。
なぜバージョン 11.4.2 への更新でサイトが壊れたのか

Booking Calendar は無料版(WordPress.org 配布)と、追加機能を提供する Pro 版(開発元サイトで購入)が連携して動作する設計になっている。無料版は管理画面の「プラグイン」から自動更新される一方、Pro 版は手動で更新する必要がある。両者のバージョンが食い違うと、共有する関数やデータベース構造に不整合が生じ、PHP の致命的エラーを引き起こして画面が表示されなくなる。
とくに 11.4.2 では内部 API の変更が加えられており、Pro 版が旧バージョンのまま無料版だけを更新すると競合が起きやすい。この状態で WordPress の「このサイトで重大なエラーが発生しました」というメッセージが表示されたり、管理画面にアクセスできなくなったりする。
サイトを元に戻す具体的な手順

以下の手順で、無料版と Pro 版を安全に最新へ揃える。作業前に必ずサイト全体のバックアップを取得しておく。
/wp-content/plugins/ にアクセスするbooking → booking_old)プラグインフォルダを特定して無効化する
サイトが壊れて管理画面に入れない場合は、FTP(File Transfer Protocol)クライアントやレンタルサーバーのファイルマネージャを使う。/wp-content/plugins/ ディレクトリ内に、無料版(通常は booking または booking-calendar)と Pro 版(booking-calendar-pro や wpdev-booking など)のフォルダが存在する。両方をリネームすれば、WordPress はプラグインを強制的に無効化し、サイトが最低限の状態で表示されるようになる。リネーム後のフォルダ名は削除せず控えておく。
無料版を最新にして Pro 版を再適用する
管理画面にアクセスできる状態になったら、プラグイン一覧画面で一度 Booking Calendar を削除する。削除しても予約データはデータベースに保持されるため、消えることはない。その後「新規追加」から再度 Booking Calendar 11.4.2 をインストールし有効化する。
続いて開発元サイト(wpbookingcalendar.com)のアカウントページから、無料版と同一バージョン(11.4.2)に対応した Pro 版の ZIP ファイルをダウンロードする。管理画面の「プラグイン」→「新規追加」→「プラグインのアップロード」から ZIP を投入し、有効化後にライセンスキーを入力すれば復旧が完了する。Pro 版の最新ファイルが入手できない場合は、開発元のサポートへ直接更新ファイルを依頼する。
どうしても復旧できない場合の最終手段
Pro 版の最新 ZIP が手元になく、サイトのダウンタイムが許容できない状況では、無料版を旧バージョン(11.4.1)にダウングレードする選択肢もある。WordPress.org のプラグインページにある「以前のバージョン」から 11.4.1 の ZIP を入手し、FTP で手動上書きすれば以前の動作に戻せる。ただしセキュリティ修正が含まれている可能性があるため、この状態は恒久的な対策にはならず、早期に Pro 版を最新化する必要がある。
再発を防ぐための運用ルール

Booking Calendar のように無料版と有料版が連動するプラグインは、無料版の自動更新をオフにするか、更新前に必ず Pro 版の対応バージョンがリリースされているかを確認する習慣をつける。開発元のチェンジログやメーリングリストを購読しておくと、更新のタイミングを逃さない。
また本番環境に直接適用する前に、ステージング環境(本番と同一構成のテストサイト)で無料版と Pro 版の同時更新を試すのが最も確実な予防策になる。レンタルサーバーのステージング機能を使うか、WP Staging のようなプラグインで簡易的なテスト環境を用意できる。
よくある質問
Pro 版の最新ファイルがアカウントページに見当たらない場合はどうすればよいか
開発元の公式サイトにある問い合わせフォームまたはサポートチケットから、Pro 版の最新 ZIP ファイルを直接依頼する。購入時のメールアドレスやライセンスキーを記載すれば、通常は数営業日以内にダウンロードリンクが提供される。
フォルダをリネームしたがサイトがまだ壊れている
キャッシュ系プラグインや CDN(コンテンツデリバリネットワーク / 配信網)が古いエラー画面を配信し続けている可能性がある。サーバー側のキャッシュをすべてクリアし、ブラウザのシークレットモードで確認する。また wp-content/mu-plugins/ に手動で入れたファイルが競合していないかも調べる。
ライセンスキーを入力しても Pro 版の機能が有効にならない
ライセンスキーが旧バージョン向けのまま失効している可能性がある。開発元のマイページでキーを再発行するか、サポートにキーのリセットを依頼する。ドメインを変更した場合もライセンスの再割り当てが必要になる場合がある。
この記事のポイント
- Booking Calendar 11.4.1 から 11.4.2 への更新障害は無料版と Pro 版のバージョン競合が原因
- FTP で両方のプラグインフォルダをリネームし強制無効化して管理画面へ復帰
- 無料版は削除後に 11.4.2 を再インストール、Pro 版は開発元から同一バージョンを入手
- Pro 版がすぐ用意できない場合は無料版のみ旧バージョン 11.4.1 に戻す応急処置も可能
- 再発防止には無料版の自動更新を止め、Pro 版のリリース確認後に揃えて更新する

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

WordPressをサブフォルダにインストールするとREST APIが404になる原因と直し方
WordPressをサブフォルダにインストールしている環境で、REST APIのエンドポイントが404エラーを返す場合は、プラグインがサブフォルダを考慮せずにAPIのURLを生成しているバグが原因だ。該当プラグインを最新版に更新するか、パーマリンク設定のリフレッシュで解決する。
なぜサブフォルダ環境でプラグインのAPIが404になるのか

WordPressをドキュメントルート直下ではなく/blogや/siteのようなサブフォルダにインストールした場合、REST APIのベースURLはhttps://example.com/subfolder/wp-json/となる必要がある。ところが一部のプラグインは、内部でAPIのURLを組み立てる際にこのサブフォルダを考慮しておらず、https://example.com/wp-json/...のようにルート直下を指してしまう。その結果、実在しないパスへのリクエストとなり404が返る。
今回のケースでは、プラグインが独自に追加したエンドポイント/profeedwp/v1/linkedin/company-posts/smartに対して、サブフォルダを含まない不完全なURLでリクエストを発行していた。同様の問題は、テーマや他のプラグインがrest_url()関数を正しく使わずにハードコードしたパスを参照している場合にも起こる。
解決手順

まず簡単かつ即効性のある方法として、問題のプラグインを最新版へ更新する。次に、WordPressのパーマリンク設定をリセットし、REST APIのルートURLが正しく再構築されるか確認する。これで直らない場合は、手動でrest_url()が返す値を検証し、他のプラグインとの競合を調べる。
プラグインを最新版に更新する
本件ではバージョン1.6.10で修正が行われている。管理画面の「プラグイン」→「インストール済みプラグイン」から対象プラグインを確認し、更新が表示されていれば適用する。更新が出ていない場合は、一度プラグインを削除して再インストールするか、開発元の公式ページから修正版がリリースされていないか確認する。
パーマリンク設定をリセットする
プラグインの更新で直らなかった場合、パーマリンク構造の再保存でWordPress内部のルーティングをリフレッシュできる。「設定」→「パーマリンク」を開き、現在選択されている設定をそのままの状態で「変更を保存」をクリックする。これにより.htaccessの再生成と、REST APIのルート定義が再構築される。サブフォルダ環境では特に、リライトルールが正しくサブフォルダをプレフィックスとして含む必要があるため、この一手順で解決するケースが多い。
rest_url() の戻り値を検証する
根本原因がプラグイン側のURL組み立てにあるかどうかを切り分けるには、WordPressが正しいREST APIのルートURLを返しているかを確認する。テーマのfunctions.phpなどに次のようなテストコードを一時的に追加する。
add_action('wp_footer', function() {
echo '<!-- REST URL: ' . esc_url(rest_url()) . ' -->';
});サイトのフッター部分のHTMLソースに出力されたURLがhttps://example.com/subfolder/wp-json/の形式になっていれば、WordPress本体の認識は正しい。もし/subfolderが欠落している場合は、wp-config.phpでWP_HOMEとWP_SITEURLが正しくサブフォルダを含んだ値で定義されているか確認する。
全プラグインを無効化して競合を切り分ける
それでも404が解消しない場合、別のプラグインがREST APIのルーティングに干渉している可能性がある。すべてのプラグインを一括で無効化し、問題のエンドポイントにアクセスして200番台のレスポンスが返るかテストする。正常動作が確認できたら、プラグインを1つずつ有効化して原因のプラグインを特定する。キャッシュ系プラグインやセキュリティプラグインは、REST APIへのリクエストをブロックしたり、URLを書き換えたりする設定項目を持つことがあるため、該当するプラグインの設定もあわせて確認する。
よくある質問
サブフォルダにインストールする際にwp-config.phpで注意すべき点は?
WP_HOMEとWP_SITEURLの定数をhttps://example.com/subfolderのようにサブフォルダを含めて明示的に定義しておくと、サイトURLの誤認識を防げる。wp-config.phpに記述しなければならないわけではないが、マルチサーバー構成やリバースプロキシの背後で運用する場合は特に有効だ。
REST APIの404エラーはどのようにデバッグすればいいか?
ブラウザのデベロッパーツールのネットワークタブで、実際に送信されたリクエストURLを確認する。サブフォルダが欠落したURLでリクエストが発生している場合は、呼び出し元のJavaScriptファイルやPHPコードでURLの組み立て方をチェックする。rest_url()を使わずにハードコードされたパスが原因であることが多い。
プラグインを更新しても問題が再発する場合は?
修正パッチが適用されたバージョンでも、キャッシュの残存やデータベースに保存された古い設定値が原因で再発することがある。プラグインを完全に削除したあと、wp_optionsテーブルに残っている該当プラグインのオプションを手動で削除し、最新版を再インストールすると改善する場合がある。
サブフォルダ環境でなくてもAPIが404になる原因は?
パーマリンク設定が「基本」になっているとREST APIが動作しない。また、セキュリティプラグインが/wp-json/へのアクセスを制限しているケースもある。.htaccessのリライトルールが破損している場合も404になるため、パーマリンク設定の再保存でリフレッシュするのが初手として有効だ。
この記事のポイント
- サブフォルダ環境でプラグインのAPIが404になるのは、URLにサブフォルダが含まれない不完全なパスが原因
- 問題のプラグインを最新版に更新し、パーマリンク設定を再保存するのが解決の基本手順
- rest_url() の戻り値とwp-config.phpの設定を確認し、WordPress本体のURL認識が正しいか検証する
- 全プラグインの無効化で競合を切り分け、キャッシュやセキュリティ系プラグインの干渉を疑う

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