DISABLE_WP_CRON = true ne scelle pas l'endpoint wp-cron.php ; cela empêche seulement WordPress de déclencher sa propre requête loopback. Le fichier reste accessible depuis le web, de sorte que n'importe qui peut toujours l'appeler et forcer un bootstrap complet de WordPress.

Ce point d'entrée caché peut gaspiller du CPU, de la mémoire et des workers PHP, en particulier sur les sites à fort trafic. Si vous pensiez avoir fermé la porte, ce n'est pas encore le cas.

Pourquoi ce paramètre est souvent mal compris

Lorsque WordPress exécute une tâche planifiée, il tente d'abord d'effectuer une requête HTTP rapide vers son propre fichier wp-cron.php. Définir DISABLE_WP_CRON sur true indique au cœur (core) d'ignorer cette requête interne. Le cœur ne modifie pas la configuration du serveur web et n'ajoute aucune couche d'authentification à wp-cron.php. Le script reste une URL publique qui renvoie un statut 200, même si le processus PHP s'interrompt prématurément.

Un attaquant qui découvre l'URL peut la solliciter de manière répétée, forçant WordPress à charger tous les plugins, les thèmes et la base de données à chaque fois. Sur un hébergement mutualisé ou un site disposant de peu de workers PHP, ce point d'entrée unique peut devenir un vecteur de déni de service (DoS).

Ce qu'il faut réellement faire

Pour transférer les tâches planifiées vers un planificateur au niveau du système (cron, systemd-timer, etc.) et fermer la porte publique, suivez ces cinq étapes.

1. Désactiver la boucle de retour (loopback) interne

Ajoutez la ligne

define( 'DISABLE_WP_CRON', true );

dans wp-config.php. Cela empêche WordPress de tenter sa propre requête HTTP, mais cela n'arrête pas les appels externes.

2. Bloquer wp-cron.php au niveau du serveur web

Avec Nginx, par exemple, insérez un bloc location qui renvoie une erreur 403 Forbidden :

location = /wp-cron.php {
    return 403;
}

Le serveur rejette désormais la requête avant même que PHP ne démarre, éliminant ainsi le coût du bootstrap.

3. Ajouter un mu-plugin comme filet de sécurité

Créez un plugin "must-use" (placé dans wp-content/mu-plugins) qui journalise toute requête atteignant wp-cron.php et s'arrête avec un code 403. Cela permet de capturer les requêtes qui contourneraient la règle du serveur — par exemple via un autre nom d'hôte ou une règle de bordure (edge rule) de CDN.

4. Supprimer les appels asynchrones d'Action Scheduler

De nombreux plugins utilisent la bibliothèque Action Scheduler, qui peut générer ses propres requêtes loopback. Utilisez un hook sur action_scheduler_queue_runner pour interrompre l'exécution prématurément pour les requêtes non-CLI, empêchant ainsi la bibliothèque de tenter d'ouvrir ses propres portes.

5. Détacher le gestionnaire de file d'attente du hook WP-Cron

Supprimez le gestionnaire de file d'attente par défaut d'Action Scheduler qui est attaché au hook cron wp. Cela garantit que la file d'attente ne s'exécute que lorsque vous la déclenchez explicitement en ligne de commande.

Exécuter les tâches de la bonne manière

Une fois l'endpoint public scellé, utilisez le planificateur du système pour invoquer WordPress une fois par minute (ou selon la cadence souhaitée) via WP-CLI :

wp cron event run --due-now

Cette commande unique traite les événements cron du cœur et la file d'attente d'Action Scheduler dans un environnement contrôlé, en utilisant le même processus PHP que vous utiliseriez pour n'importe quelle autre tâche CLI.

Des bénéfices mesurables

  • Sécurité – Aucun utilisateur non authentifié ne peut lancer de lourdes tâches de fond.
  • Performance – Les workers PHP restent disponibles pour les vrais visiteurs ; les pics de mémoire causés par des appels cron erratiques disparaissent.
  • Fiabilité – La planification devient proactive ; vous savez exactement quand une tâche s'exécute car elle est pilotée par le cron du système, et non par le chargement d'une page par un visiteur.

Points de vigilance après le changement

Ne vous fiez pas au code de statut HTTP de wp-cron.php ; il peut toujours renvoyer 200 même lorsqu'il est bloqué par PHP. À la place :

  • Surveillez la taille de la file d'attente Action Scheduler. Une file d'attente qui s'allonge signale souvent des exécutions manquées.
  • Vérifiez les journaux (logs) du serveur pour les entrées « 403 » provenant du bloc location de wp-cron.php.
  • Observez le nombre de processus PHP-FPM ou FastCGI pendant les pics de trafic pour confirmer que la charge a diminué.

Une mise en garde

Certains administrateurs laissent DISABLE_WP_CRON sur false car ils comptent sur le faible trafic de leurs sites pour déclencher le cron naturellement. L'approche ci-dessus supprime entièrement cette dépendance, mais elle ajoute une étape de maintenance : vous devez vous assurer que le planificateur du système fonctionne de manière fiable. Si le démon cron du serveur échoue, les tâches planifiées s'arrêtent. Couplez cette configuration avec une surveillance du service cron du système pour éviter ce piège.

En résumé : définir DISABLE_WP_CRON sur true empêche seulement WordPress de s'appeler lui-même ; cela ne ferme pas l'endpoint public wp-cron.php. Bloquez le fichier au niveau du serveur web, ajoutez une solution de repli via un mu-plugin, et dirigez tout le travail planifié vers un planificateur système via WP-CLI. Cela sécurise le site, réduit le travail PHP inutile et vous donne un contrôle précis sur l'exécution des tâches de fond.