Gérer un seul site WordPress, ça va encore — mais quand le parc s’étend à une dizaine d’installations, les audits manuels deviennent vite un cauchemar chronophage. WP-CLI, on le connaît souvent pour les mises à jour en ligne de commande, mais son potentiel va bien au-delà : sécurité, performance, reporting automatisé… tout ça scriptable et planifiable. Dans cet article, on va voir comment passer à la vitesse supérieure et transformer vos audits en processus entièrement automatisés.
WP-CLI et la sécurité : pourquoi automatiser vos audits ?
Gérer la sécurité d’un seul site WordPress, c’est déjà une tâche à part entière. Alors quand on commence à en administrer cinq, dix, ou vingt… ça devient vite un cauchemar logistique. L’automatisation n’est plus un luxe — c’est une nécessité absolue.
Les limites des audits manuels sur un parc de sites WordPress
Soyons honnêtes : faire un audit de sécurité à la main sur un site, ça prend du temps. Se connecter à chaque back-office, vérifier les versions des plugins, contrôler les utilisateurs administrateurs, inspecter les fichiers suspects… Multipliez ça par dix sites, et vous avez facilement une demi-journée perdue chaque semaine.
Et encore, c’est dans le meilleur des cas. En pratique, on oublie des sites, on bâcle certaines vérifications parce qu’on est pressé, ou pire : on laisse passer une mise à jour critique parce qu’on pensait l’avoir déjà faite sur ce serveur-là. Les incohérences s’accumulent, et c’est exactement là que les failles de sécurité apparaissent.
- Temps perdu : chaque audit manuel représente 20 à 45 minutes par site
- Risque d’oubli : sans automatisation, certains sites passent entre les mailles du filet
- Incohérences : les procédures varient d’un opérateur à l’autre, d’une semaine à l’autre
- Réactivité limitée : impossible de détecter une anomalie en temps réel sans monitoring automatisé
Au-delà de cinq sites, l’approche manuelle n’est tout simplement plus viable. Il faut industrialiser.
WP-CLI comme socle d’un workflow DevOps sécurisé
C’est là qu’intervient WP-CLI. Pour ceux qui ne connaissent pas encore, WP-CLI est l’outil officiel en ligne de commande pour WordPress. Il permet d’interagir avec une installation WordPress directement depuis le terminal, sans passer par l’interface graphique : mettre à jour des plugins, gérer les utilisateurs, exécuter des requêtes en base de données, et bien plus encore.
La version stable actuelle est la 2.10.x, et son installation est très simple :
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
Une fois installé, un simple wp --version vous confirmera que tout est en ordre.
Dans un contexte DevOps, WP-CLI devient le socle idéal pour construire des scripts d’audit automatisés. On peut l’intégrer dans des pipelines CI/CD, des tâches cron, ou des outils d’orchestration comme Ansible. La puissance vient de sa capacité à être scripté et combiné avec d’autres commandes shell (grep, awk, jq…). Donc au lieu de cliquer dans dix interfaces différentes, on lance un seul script qui parcourt l’ensemble du parc en quelques minutes.
Prérequis : configuration et accès SSH multi-sites
Avant de se lancer dans l’automatisation, quelques prérequis sont indispensables. Le premier, et le plus évident : un accès SSH à vos serveurs. WP-CLI fonctionne en local sur le serveur hébergeant WordPress, donc sans SSH, difficile de l’utiliser à distance de façon automatisée.
Côté compatibilité hébergeur, WP-CLI fonctionne très bien sur les VPS et serveurs dédiés. Certains hébergements mutualisés avancés (comme LWS, o2switch, ou Infomaniak) proposent également un accès SSH — pensez à vérifier votre offre.
Ensuite, pour gérer plusieurs sites proprement, on crée un fichier wp-cli.yml à la racine de chaque installation WordPress. Ce fichier permet de définir le chemin vers WordPress, l’utilisateur système à utiliser, et d’autres options par défaut. Mais le vrai gain de temps vient des alias WP-CLI : en définissant des alias comme @production ou @staging dans un fichier ~/.wp-cli/config.yml, on peut cibler n’importe quel environnement d’une simple commande :
wp @production plugin list --status=inactive
wp @staging core check-update
Un exemple de configuration d’alias dans ~/.wp-cli/config.yml :
@production:
ssh: user@mon-serveur.com
path: /var/www/mon-site/
@staging:
ssh: user@staging.mon-serveur.com
path: /var/www/staging/
C’est cette mécanique d’alias qui rend WP-CLI vraiment puissant pour un parc multi-sites. On définit ses environnements une bonne fois pour toutes, et ensuite les scripts d’audit peuvent itérer dessus automatiquement.
Automatiser les audits de sécurité avec WP-CLI
On a posé les bases dans la section précédente : WP-CLI est l’outil idéal pour automatiser ce genre de tâches répétitives. Maintenant, on passe aux choses sérieuses. Voici comment construire un audit de sécurité solide, commande par commande.
Détecter les plugins et thèmes vulnérables via WP Vulnerability API
La première étape d’un bon audit, c’est de savoir si vos plugins exposent des failles connues. WP-CLI seul ne fait pas cette vérification, mais combiné à l’API WPScan (disponible sur wpscan.com), ça devient redoutable.
On commence par récupérer la liste des plugins au format JSON :
wp plugin list --format=json | jq '.[].name'
Ensuite, pour chaque plugin, on interroge l’API WPScan avec sa clé (gratuite jusqu’à 25 requêtes/jour) :
PLUGIN_SLUG="woocommerce"
API_KEY="VOTRE_CLE_API"
curl -s "https://wpscan.com/api/v3/plugins/${PLUGIN_SLUG}" \
-H "Authorization: Token token=${API_KEY}" | jq '.vulnerabilities'
Avec jq, on peut filtrer directement les plugins qui retournent un tableau de vulnérabilités non vide :
wp plugin list --status=active --format=json | jq -r '.[].name' | while read plugin; do
RESULT=$(curl -s "https://wpscan.com/api/v3/plugins/${plugin}" \
-H "Authorization: Token token=${API_KEY}")
VULN_COUNT=$(echo "$RESULT" | jq '.vulnerabilities | length')
if [ "$VULN_COUNT" -gt 0 ]; then
echo "⚠️ $plugin : $VULN_COUNT vulnérabilité(s) détectée(s)"
fi
done
C’est basique, mais déjà très efficace pour un premier tri. L’API Wordfence propose une alternative similaire si vous préférez.
Vérifier les mises à jour en attente et les fichiers core modifiés
Un fichier core modifié, c’est souvent le signe d’une compromission. WP-CLI embarque une commande native pour vérifier l’intégrité de WordPress :
wp core verify-checksums
Cette commande compare les fichiers de votre installation avec les checksums officiels de WordPress.org. Si un fichier a été altéré, il apparaît immédiatement dans la sortie. On peut faire la même chose pour les plugins :
wp plugin verify-checksums --all
Pour les mises à jour en attente, deux commandes utiles :
# Nombre de plugins à mettre à jour
wp plugin list --update=available --format=count
# Simuler une mise à jour du core sans l'appliquer
wp core update --dry-run
Le --dry-run est particulièrement pratique pour inclure dans un rapport sans risquer de casser quoi que ce soit en production. Et croyez-moi, sur un site en production, ce genre de précaution évite bien des sueurs froides.
Scanner les utilisateurs, rôles et permissions suspects
Les comptes administrateurs fantômes, c’est un classique des sites compromis. Un attaquant qui prend la main sur un WordPress crée souvent un compte admin discret pour garder un accès persistant.
Pour lister tous les administrateurs :
wp user list --role=administrator --format=table
Pour un audit plus détaillé avec les dates de création et les emails :
wp user list --fields=ID,user_login,user_email,user_registered,roles --format=table
On peut ensuite filtrer les comptes créés récemment (par exemple les 30 derniers jours) avec un peu de Bash :
THRESHOLD=$(date -d "30 days ago" +%Y-%m-%d)
wp user list --fields=ID,user_login,user_email,user_registered --format=json | \
jq --arg threshold "$THRESHOLD" \
'.[] | select(.user_registered > $threshold)'
Et pour détecter des emails suspects (domaines jetables, patterns inhabituels), on peut ajouter un grep sur des domaines connus comme mailinator.com ou guerrillamail.com. Ce n’est pas infaillible, mais ça couvre les cas les plus évidents.
Créer un script Bash d’audit de sécurité complet
Bon, on a toutes les briques. Il ne reste plus qu’à assembler le tout dans un script security-audit.sh réutilisable. L’idée, c’est de boucler sur plusieurs sites en utilisant --path pour cibler chaque installation WordPress :
#!/bin/bash
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
API_KEY="VOTRE_CLE_WPSCAN"
SITES=("/var/www/site1" "/var/www/site2" "/var/www/site3")
for SITE_PATH in "${SITES[@]}"; do
echo -e "\n==============================="
echo -e "🔍 Audit : ${YELLOW}${SITE_PATH}${NC}"
echo "==============================="
# 1. Intégrité du core
echo -e "\n[Core] Vérification des checksums..."
CORE_CHECK=$(wp --path="$SITE_PATH" core verify-checksums 2>&1)
if echo "$CORE_CHECK" | grep -q "Error"; then
echo -e "${RED}✗ Fichiers core modifiés détectés !${NC}"
echo "$CORE_CHECK"
else
echo -e "${GREEN}✓ Core WordPress intact${NC}"
fi
# 2. Mises à jour en attente
UPDATE_COUNT=$(wp --path="$SITE_PATH" plugin list --update=available --format=count 2>/dev/null)
echo -e "\n[Plugins] Mises à jour en attente : ${YELLOW}${UPDATE_COUNT}${NC}"
# 3. Utilisateurs admin récents
echo -e "\n[Users] Comptes administrateurs :"
wp --path="$SITE_PATH" user list --role=administrator \
--fields=ID,user_login,user_email,user_registered --format=table
# 4. Vulnérabilités plugins (WPScan API)
echo -e "\n[Vulns] Scan des vulnérabilités..."
wp --path="$SITE_PATH" plugin list --status=active --format=json | \
jq -r '.[].name' | while read plugin; do
RESULT=$(curl -s "https://wpscan.com/api/v3/plugins/${plugin}" \
-H "Authorization: Token token=${API_KEY}")
VULN_COUNT=$(echo "$RESULT" | jq '.vulnerabilities | length' 2>/dev/null)
if [ "$VULN_COUNT" -gt 0 ] 2>/dev/null; then
echo -e "${RED}⚠️ $plugin : $VULN_COUNT vulnérabilité(s)${NC}"
fi
done
done
echo -e "\n✅ Audit terminé."
Ce script, quand on gère 10, 20 ou 30 sites WordPress, c’est un gain de temps considérable. Là où un audit manuel prendrait une demi-journée, on tombe à quelques minutes d’exécution. On peut ensuite rediriger la sortie vers un fichier log (./security-audit.sh > audit-$(date +%F).log) ou l’intégrer dans une tâche cron pour une exécution hebdomadaire automatique.
Pour les environnements avec des alias WP-CLI configurés (via ~/.wp-cli/config.yml), on peut même remplacer le --path par les alias définis directement dans la boucle. Pratique pour les configurations multi-serveurs.
Générer des rapports de performance automatisés
On a vu comment automatiser les audits de sécurité — mais WP-CLI ne s’arrête pas là. Il peut aussi alimenter des rapports de performance complets, site par site, de façon entièrement automatisée. Et franchement, une fois qu’on a mis en place ce pipeline, on ne revient pas en arrière.
Mesurer les métriques clés avec WP-CLI et des outils tiers
Les métriques base de données en premier lieu
La base de données, c’est souvent le premier endroit où les performances se dégradent — et le plus négligé. WP-CLI permet d’en extraire les métriques essentielles en quelques commandes :
# Taille totale de la base de données
wp db size
# Nombre d'options en autoload (seuil critique : >1 MB)
wp db query 'SELECT COUNT(*) FROM wp_options WHERE autoload="yes"'
# Audit des transients
wp transient list --format=count
Le seuil des options en autoload est souvent sous-estimé. Au-delà de 1 MB d’options chargées à chaque requête, les performances chutent de façon visible. Si vous dépassez ce seuil, wp db optimize et wp cache flush sont vos premiers réflexes.
Les métriques applicatives
En complément, on peut collecter des données sur l’état général du site :
wp option get blogname
wp option get siteurl
wp post list --post_status=publish --format=count
wp plugin list --status=inactive --format=count
Le dernier point mérite attention : un plugin inactif n’est pas inoffensif. Il reste présent dans le système de fichiers, peut contenir des vulnérabilités, et contribue à alourdir le backend. Les recenser automatiquement, c’est déjà identifier des candidats à la suppression.
Coupler avec des outils tiers : Lighthouse et au-delà
C’est là que ça devient vraiment puissant. On peut déclencher un audit Lighthouse via l’API PageSpeed Insights de Google (la clé API est gratuite) directement depuis un script Bash, et stocker les résultats dans un fichier de log daté :
#!/bin/bash
SITE_URL="https://mon-site.fr"
API_KEY="VOTRE_CLE_API"
DATE=$(date +%Y-%m-%d)
LOG_FILE="rapport_perf_${DATE}.log"
RESULT=$(curl -s "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${SITE_URL}&key=${API_KEY}&strategy=mobile")
PERF=$(echo $RESULT | jq '.lighthouseResult.categories.performance.score')
LCP=$(echo $RESULT | jq '.lighthouseResult.audits["largest-contentful-paint"].displayValue')
CLS=$(echo $RESULT | jq '.lighthouseResult.audits["cumulative-layout-shift"].displayValue')
echo "[$DATE] $SITE_URL - Performance: $PERF | LCP: $LCP | CLS: $CLS" >> $LOG_FILE
Ce script récupère les scores Performance, LCP et CLS, et les persiste dans un log horodaté. On peut évidemment étendre ça avec le FID (ou INP maintenant, selon la version de l’API).
Pour les environnements plus avancés, le couplage avec New Relic ou Datadog permet d’aller beaucoup plus loin : métriques temps réel, alertes sur seuils, dashboards centralisés. Et si vous gérez la génération de sitemaps, l’outil wp-cli/google-sitemap-generator-cli s’intègre proprement dans ce pipeline.
Formater et envoyer le rapport
Un rapport qui reste dans un fichier de log, ça ne sert pas à grand-chose si personne ne le lit. L’idée, c’est de générer un fichier Markdown (ou HTML) structuré, avec une section par site :
# Rapport de performance — 2024-11-15
## mon-site.fr
- **Score Performance** : 87/100
- **LCP** : 2.4s
- **CLS** : 0.05
- **Plugins inactifs** : 3
- **Options autoload** : 0.8 MB ✅
- **Transients** : 142
## autre-site.fr
- **Score Performance** : 61/100 ⚠️
- **LCP** : 4.1s ❌
...
Ensuite, deux options pour diffuser ce rapport. La plus simple : mail en ligne de commande.
mail -s "Rapport performance WordPress - $(date +%Y-%m-%d)" equipe@mon-agence.fr < rapport_perf.md
Mais pour une équipe DevOps, un webhook Slack est souvent plus pratique :
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"📊 Rapport de performance disponible — voir rapport_perf_2024-11-15.log"}' \
https://hooks.slack.com/services/VOTRE/WEBHOOK/ICI
Bon, le contenu du message peut être enrichi (blocks Slack, résumé inline, etc.), mais même cette version minimaliste suffit à notifier l’équipe en temps réel. Et couplé au cron job qu’on mentionnait plus tôt, le tout tourne en autonomie complète.
Planifier et industrialiser vos audits avec Cron et CI/CD
On a maintenant des scripts d’audit solides, des rapports de performance automatisés, et une bonne couverture sécurité. Mais si vous devez les lancer manuellement chaque semaine… l’automatisation n’est qu’à moitié faite. L’étape suivante, c’est l’industrialisation : planifier, intégrer dans vos pipelines, et ne plus y penser.
Automatisation via Crontab : planifier les audits hebdomadaires
La méthode la plus directe pour les environnements sans CI/CD, c’est le bon vieux cron. Un exemple concret pour lancer votre audit chaque lundi à 6h00 :
0 6 * * 1 /usr/local/bin/security-audit.sh >> /var/log/wp-audit.log 2>&1
Simple, efficace. Le 2>&1 redirige également les erreurs dans le log — ce qui est essentiel pour diagnostiquer un éventuel problème silencieux.
Mais attention : les logs grossissent vite sur plusieurs sites. Mettez en place logrotate pour éviter de saturer votre disque. Un fichier /etc/logrotate.d/wp-audit minimal pourrait ressembler à ça :
/var/log/wp-audit.log {
weekly
rotate 4
compress
missingok
notifempty
}
Et avant de planifier quoi que ce soit, testez toujours votre script manuellement avec le mode debug de Bash :
bash -x /usr/local/bin/security-audit.sh
Vous verrez chaque commande s’exécuter en temps réel. C’est le meilleur moyen de repérer un chemin incorrect, une variable non définie, ou un WP-CLI qui n’est pas dans le $PATH du contexte cron (c’est un classique !).
Intégrer WP-CLI dans un pipeline GitHub Actions ou GitLab CI
Pour les équipes qui versionnent leur infrastructure et leurs scripts — ce qui devrait être votre cas — l’intégration dans un pipeline CI/CD apporte un niveau supérieur de traçabilité et de collaboration.
GitHub Actions
Créez un fichier .github/workflows/wp-audit.yml dans votre dépôt. Voici un exemple fonctionnel :
name: WP Security Audit
on:
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:
jobs:
audit:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run WP-CLI audit via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
bash /usr/local/bin/security-audit.sh > /tmp/wp-audit-report.txt 2>&1
cat /tmp/wp-audit-report.txt
- name: Upload audit report as artifact
uses: actions/upload-artifact@v4
with:
name: wp-audit-report
path: /tmp/wp-audit-report.txt
Le déclenchement est double : automatique chaque lundi via schedule: cron, ou manuel via workflow_dispatch (pratique pour un audit à la demande avant une mise en production). Les résultats sont stockés comme artefacts du pipeline, consultables directement dans l’interface GitHub. Vous pouvez également poster un résumé en commentaire de PR via l’API GitHub si vous voulez aller plus loin.
GitLab CI
La variante GitLab avec un runner SSH est tout aussi propre. Voici un .gitlab-ci.yml de base :
stages:
- audit
wp_security_audit:
stage: audit
image: alpine:latest
before_script:
- apk add --no-cache openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh && chmod 700 ~/.ssh
- ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts
script:
- ssh $SSH_USER@$SSH_HOST "bash /usr/local/bin/security-audit.sh"
artifacts:
paths:
- audit-report.txt
expire_in: 1 week
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- if: '$CI_PIPELINE_SOURCE == "web"'
Les variables SSH_PRIVATE_KEY, SSH_HOST et SSH_USER sont stockées dans GitLab CI/CD Variables (Settings → CI/CD → Variables), marquées comme « protected » et « masked ». Jamais en dur dans le code — c’est non négociable. Une clé SSH exposée dans un dépôt public, même l’espace d’un instant, c’est une faille potentielle sur tous vos serveurs.
Bonnes pratiques finales
Quelques points sur lesquels je veux insister avant de conclure :
- Clés SSH ed25519 uniquement : plus courtes, plus sûres, sans passphrase pour les contextes automatisés (la clé privée doit être stockée de façon sécurisée côté CI).
- Principe du moindre privilège : l’utilisateur système qui exécute WP-CLI ne doit pas être root. Créez un utilisateur dédié avec accès uniquement aux répertoires WordPress concernés.
- Versionnez vos scripts d’audit dans Git : c’est la base. Historique des modifications, revue de code, rollback possible — tout ça devient gratuit.
Bon, une fois que tout ça est en place… vous n’avez plus grand chose à faire. Le système tourne, les rapports arrivent, les alertes se déclenchent si besoin. C’est exactement ça, l’objectif : transformer une corvée hebdomadaire chronophage en un processus qui fonctionne sans vous. Et ça, c’est du temps libéré pour ce qui compte vraiment dans votre workflow de développement.
