2026年11月12日

2026年11月12日

Masquer la version de WordPress : generator, ver=, readme.html

Cet article est une édition localisée de l'original japonais. Lire l'original en japonais

Par défaut, WordPress écrit son numéro de version dans le HTML des pages et dans les flux. Un attaquant peut s'en servir pour chercher si la version présente des vulnérabilités connues. Cet article décrit les endroits où la version s'affiche et la façon de la masquer. Son contenu date d'octobre 2026.

Il faut d'abord savoir que masquer la version n'est qu'une mesure complémentaire. On peut aussi deviner la version d'après le contenu des fichiers CSS et JavaScript, entre autres : la masquer n'empêche donc pas forcément l'identification. Le plus efficace reste de maintenir à jour le cœur de WordPress, les extensions et les thèmes.

Où la version s’affiche

Emplacement Contenu affiché Solution
<head> du HTML Une balise comme <meta name="generator" content="WordPress 6.9.4"> Filtre the_generator
Flux RSS et Atom Une ligne comme <generator>https://wordpress.org/?v=6.9.4</generator> Là aussi, filtre the_generator
URL des CSS et JavaScript Un ?ver= comme style.min.css?ver=6.9.4 Filtres style_loader_src et script_loader_src
En-têtes HTTP X-Powered-By: PHP/8.3.x (version de PHP, et non de WordPress) expose_php dans php.ini
readme.html Le fait que WordPress est utilisé (le readme.html actuel n'indique pas de numéro de version) Refuser l'accès

Les informations du site renvoyées par /wp-json/ de l'API REST (nom, description, URL, fuseau horaire, espaces de noms, etc.) ne contiennent pas la version de WordPress. Il n'est pas nécessaire de réduire la sortie de l'API REST dans le but de masquer la version.

Étape 1 : vérifier ce qui est affiché actuellement

Remplacez l'URL par celle de votre site et exécutez ces commandes sur votre ordinateur ou sur le serveur. Si vous utilisez une extension de cache ou un CDN, videz le cache après vos modifications avant de vérifier.

# Balise generator du HTML
curl -s https://example.com/ | grep -i 'name="generator"'

# generator du flux
curl -s https://example.com/feed/ | grep -i '<generator>'

# Liste des valeurs de ver= attachées aux CSS et JS
curl -s https://example.com/ | grep -oE 'ver=[0-9][0-9.]*' | sort | uniq -c

# En-tête HTTP X-Powered-By
curl -sI https://example.com/ | grep -i 'x-powered-by'

# readme.html est-il lisible ? (200 : lisible)
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html

Si la liste des ver= contient la même valeur que la version de WordPress affichée dans « Tableau de bord » → « Mises à jour » (Dashboard → Updates) de l'administration, la version de WordPress peut être déduite de ces CSS ou JS. Quand le cœur de WordPress ou le thème charge un CSS ou un JS sans préciser de version, la version de WordPress est placée dans ver=.

Étape 2 : choisir où placer le code

Placez le code de cet article à l'un des deux endroits suivants.

  • mu-plugin (recommandé) : un fichier PHP placé dans le dossier wp-content/mu-plugins/ (à créer s'il n'existe pas) est chargé sans aucune opération d'activation. L'effet persiste même si vous changez de thème
  • functions.php du thème enfant : si vous l'écrivez dans le functions.php du thème parent, il sera effacé par une mise à jour du thème

Avec un mu-plugin, regroupez le code de l'étape suivante dans un seul fichier, nommé par exemple wp-content/mu-plugins/hide-wp-version.php.

Étape 3 : masquer la version dans la balise generator et dans ver=

<?php
/**
 * Plugin Name: Hide WordPress Version
 * Description: Masque la version de WordPress affichée par la balise generator et par le ver= des CSS et JS.
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// Vide le <meta name="generator"> du HTML et le <generator> des flux.
add_filter( 'the_generator', '__return_empty_string' );

/**
 * Remplace le ver= des CSS et JS par une autre valeur, uniquement lorsqu'il est identique à la version de WordPress.
 * Comme ver= est remplacé et non supprimé, le cache du navigateur est actualisé après une mise à jour de WordPress.
 */
function wpdr_replace_wp_version_query( $src ) {
	if ( ! is_string( $src ) || '' === $src ) {
		return $src;
	}

	$query = wp_parse_url( $src, PHP_URL_QUERY );
	if ( empty( $query ) ) {
		return $src;
	}

	parse_str( $query, $args );
	$wp_version = get_bloginfo( 'version' );

	if ( isset( $args['ver'] ) && $args['ver'] === $wp_version ) {
		$src = add_query_arg( 'ver', substr( wp_hash( $wp_version ), 0, 10 ), $src );
	}

	return $src;
}
add_filter( 'style_loader_src', 'wpdr_replace_wp_version_query', 20 );
add_filter( 'script_loader_src', 'wpdr_replace_wp_version_query', 20 );

Les points à retenir sont les suivants.

  • Le filtre the_generator agit à la fois sur la balise generator du HTML et sur le generator des flux. remove_action( 'wp_head', 'wp_generator' ); ne supprime que la balise du HTML et n'agit donc pas sur les flux
  • Si vous supprimez tous les ?ver=, le navigateur peut continuer à utiliser d'anciens CSS et JS après une mise à jour d'extension ou de thème. Le code ci-dessus remplace par une autre chaîne, calculée à partir de la version, uniquement les valeurs identiques à la version de WordPress. Comme la valeur change quand vous mettez WordPress à jour, le cache est actualisé
  • Les ver= auxquels une extension ou un thème a attribué son propre numéro de version ne sont pas modifiés

Après l'enregistrement, vérifiez avec les commandes de l'étape 1 que generator n'apparaît plus et que la liste des ver= ne contient plus la version de WordPress. Si vous utilisez une extension de cache, videz-le avant de vérifier.

Étape 4 : supprimer l’en-tête X-Powered-By

X-Powered-By est un en-tête ajouté par PHP et non par WordPress ; il indique la version de PHP. Pour le supprimer, mettez expose_php sur Off dans le fichier de configuration de PHP (php.ini). Ce réglage ne peut être modifié que dans php.ini.

expose_php = Off

Voici un exemple pour un VPS Ubuntu avec PHP-FPM (adaptez 8.3 à la version de PHP que vous utilisez).

# Vérifier le réglage actuel
grep -n '^expose_php' /etc/php/8.3/fpm/php.ini

# Après modification, redémarrer PHP-FPM
sudo systemctl restart php8.3-fpm

Le php.ini des paquets Ubuntu a expose_php = Off par défaut. Si l'en-tête apparaît, vérifiez qu'un autre php.ini n'est pas utilisé. Sur un hébergement mutualisé, il est parfois possible de le modifier dans les réglages PHP de l'administration, et parfois non.

Si vous ne pouvez pas modifier php.ini, il est aussi possible de retirer l'en-tête depuis le code de WordPress. Cependant, send_headers est un hook exécuté quand WordPress génère les pages publiques : il n'agit pas sur l'administration ni sur la page de connexion.

add_action( 'send_headers', function () {
	header_remove( 'X-Powered-By' );
} );

Étape 5 : refuser l’accès à readme.html et license.txt

readme.html et license.txt sont des fichiers du cœur de WordPress. Le readme.html actuel n'indique pas de numéro de version, mais il révèle que WordPress est utilisé.

Même si vous les supprimez, ils reviennent à la mise à jour du cœur de WordPress. Plutôt que de les supprimer, il est moins fastidieux de refuser l'accès côté serveur web.

Avec Apache (.htaccess)

Ajoutez-le au .htaccess situé dans le dossier de WordPress. Ce qui se trouve entre # BEGIN WordPress et # END WordPress est réécrit par WordPress : écrivez donc en dehors de ce bloc. Il s'agit de la syntaxe d'Apache 2.4 (Order et Deny from all sont l'ancienne syntaxe d'Apache 2.2).

<FilesMatch "^(readme\.html|license\.txt)$">
    Require all denied
</FilesMatch>

Avec Nginx

Ajoutez-le dans le bloc server du site, puis vérifiez la configuration avant de la recharger.

location ~* ^/(readme\.html|license\.txt)$ {
    deny all;
}
sudo nginx -t && sudo systemctl reload nginx

Après l'ajout, exécutez curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html et vérifiez que vous obtenez un 403.

Ce que masquer ne permet pas d’empêcher

  • Le contenu des fichiers CSS et JS de WordPress diffère légèrement d'une version à l'autre : en récupérant les fichiers et en les comparant, on peut deviner la version
  • Le readme.txt ou le ver= des extensions et des thèmes peut révéler la version de l'extension. Ce sont plutôt les failles des extensions que celles du cœur qui sont visées
  • Les personnes qui peuvent se connecter à l'administration voient toujours la version comme avant

C'est pourquoi, en plus de masquer la version, mettez à jour le cœur, les extensions et les thèmes, supprimez les extensions inutilisées et désactivez l'édition de fichiers dans l'administration.

Résumé

  • La version s'affiche principalement dans generator (HTML et flux) et dans le ?ver= des CSS et JS. Le /wp-json/ de l'API REST ne contient pas la version de WordPress
  • add_filter( 'the_generator', '__return_empty_string' ); supprime à la fois le generator du HTML et celui des flux
  • Ne supprimez pas ?ver= : remplacez seulement les valeurs identiques à la version de WordPress, pour ne pas bloquer l'actualisation du cache
  • Supprimez X-Powered-By avec expose_php = Off dans php.ini
  • readme.html revient après une mise à jour même si on le supprime : refusez donc l'accès côté serveur web
  • Masquer est une mesure complémentaire ; l'essentiel est de continuer à mettre à jour

Articles associés :

Une question sur WordPress ? L'éditeur de ce site est basé au Japon et répond en japonais. Contact (en japonais)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲