DISABLE_WP_CRON = true は wp-cron.php エンドポイントを封鎖するものではありません。単に WordPress が自身のループバックリクエストを実行するのを停止するだけです。ファイル自体はウェブからアクセス可能な状態のままなので、誰でもアクセスして WordPress のフルブートストラップを強制できてしまいます。
この隠れたエントリーポイントは、特にアクセス数の多いサイトにおいて、CPU、メモリ、PHP ワーカーを浪費させる可能性があります。「ドアを閉めた」と思っていても、実際にはまだ開いたままなのです。
なぜこの設定は誤解されやすいのか
WordPress がスケジュールされたタスクを実行するとき、まず自身の wp-cron.php ファイルに対して素早い HTTP リクエストを試みます。DISABLE_WP_CRON を true に設定すると、コアは内部リクエストをスキップします。しかし、コアはウェブサーバーの設定を変更したり、wp-cron.php に認証レイヤーを追加したりすることはありません。PHP プロセスが途中で中断されたとしても、スクリプトは 200 ステータスを返す公開 URL のままです。
URL を発見した攻撃者が繰り返し ping を送ると、そのたびに WordPress がすべてのプラグイン、テーマ、データベースをロードすることになり、リソースを消費させることができます。共有ホストや PHP ワーカーが限られているサイトでは、この単一のエンドポイントが DoS(サービス拒否)攻撃のベクトルになり得ます。
本当に行うべきこと
スケジュールされたタスクをシステムレベルのスケジューラ(cron、systemd-timer など)に移行し、公開された「ドア」を閉じるには、次の 5 つのステップに従ってください。
1. 内部ループバックを無効にする
wp-config.php に以下の行を追加します。
define( 'DISABLE_WP_CRON', true );
これにより、WordPress が自身の HTTP リクエストを試みることはなくなりますが、外部からの呼び出しを停止するわけではありません。
2. ウェブサーバーで wp-cron.php をブロックする
例えば Nginx の場合、403 Forbidden を返す location ブロックを挿入します。
location = /wp-cron.php {
return 403;
}
これで、PHP が起動する前にサーバーがリクエストを拒否するため、ブートストラップのコストを排除できます。
3. セーフティネットとして mu-plugin を追加する
wp-content/mu-plugins に、wp-cron.php に到達したリクエストをログに記録し、403 で終了する must-use プラグインを作成します。これにより、異なるホスト名や CDN のエッジルールなどを通じて、何らかの方法でサーバーのルールをバイパスしてしまったリクエストを捕捉できます。
4. Action Scheduler の非同期呼び出しを抑制する
多くのプラグインは Action Scheduler ライブラリを使用しており、これが独自のループバックリクエストを生成することがあります。action_scheduler_queue_runner にフックし、CLI 以外のリクエストに対しては早期に return させることで、ライブラリが独自の「ドア」を開こうとするのを防ぎます。
5. WP-Cron フックからキューランナーを解除する
wp cron フックにアタッチされているデフォルトの Action Scheduler キューランナーを削除します。これにより、コマンドラインから明示的に実行したときにのみキューが動作するようになります。
正しいジョブの実行方法
公開エンドポイントを封鎖したら、システムスケジューラを使用して、WP-CLI 経由で 1 分ごと(または必要な間隔)に WordPress を呼び出します。
wp cron event run --due-now
この単一のコマンドにより、他の CLI タスクで使用するものと同じ PHP プロセスを使用して、コアの cron イベントと Action Scheduler のキューの両方を、制御された環境で処理できます。
測定可能なメリット
- セキュリティ – 認証されていないユーザーが重いバックグラウンド処理を開始することができなくなります。
- パフォーマンス – PHP ワーカーが実際の訪問者のために利用可能になり、不規則な cron へのアクセスによるメモリのスパイクが解消されます。
- 信頼性 – スケジューリングがプロアクティブ(能動的)になります。訪問者のページロードではなく、システムの cron によって駆動されるため、ジョブがいつ実行されるかを正確に把握できます。
変更後に注意すべき点
wp-cron.php の HTTP ステータスコードだけに頼らないでください。PHP によってブロックされている場合でも、200 を返すことがあります。代わりに以下を確認してください。
- Action Scheduler のキューのサイズを監視する。キューが増え続けている場合は、実行が漏れているサインであることが多いです。
wp-cron.phpの location ブロックからの「403」エントリがないか、サーバーログを確認する。- ピーク時の PHP-FPM または FastCGI のプロセス数を観察し、負荷が下がっていることを確認する。
注意事項
アクセス数の少ないサイトでは、自然に cron がトリガーされることに依存しているため、DISABLE_WP_CRON を false のままにしている管理者もいます。上記のアプローチはその依存関係を完全に排除しますが、メンテナンスの手間が増えることにもなります。つまり、システムスケジューラが確実に動作するようにしなければなりません。サーバーの cron デーモンが停止すると、スケジュールされたジョブも停止します。この落とし穴を避けるため、セットアップ時にはシステムの cron サービスの監視も併せて行ってください。
結論: DISABLE_WP_CRON を true に設定しても、WordPress が自身に ping を送るのを止めるだけであり、公開されている wp-cron.php エンドポイントを閉じることはできません。ウェブサーバーでファイルをブロックし、mu-plugin によるフォールバックを追加し、すべてのスケジュールされたタスクを WP-CLI 経由でシステムスケジューラにルーティングしてください。そうすることで、サイトのセキュリティを確保し、不要な PHP の負荷を軽減し、バックグラウンドタスクの実行タイミングを正確に制御できるようになります。
