Glossaire

Que sont les nonces dans WordPress ? Les jetons de sécurité expliqués

5 août 2026

Un nonce dans WordPress est un jeton de sécurité attaché aux formulaires, aux liens et aux requêtes AJAX pour que WordPress puisse vérifier que la requête a bien été déclenchée intentionnellement par un utilisateur connecté précis. Le nom vient de la cryptographie et signifie number used once, ce qui prête légèrement à confusion ici : un nonce WordPress n'est pas un nombre, ne sert pas une seule fois et constitue techniquement une empreinte liée à l'utilisateur, à la session et à une action précise. Il reste valide jusqu'à 24 heures. La menace contre laquelle les nonces défendent est le cross-site request forgery (CSRF), une attaque où une page malveillante soumet silencieusement une requête avec votre session connectée, par exemple pour supprimer un article ou modifier un réglage. Les nonces fonctionnent, et c'est précisément pour cela que l'erreur de sécurité la plus courante se situe de l'autre côté : un nonce prouve l'intention, pas la permission. Le code d'extension qui vérifie un nonce mais oublie le contrôle des droits avec current_user_can() est l'une des sources les plus fréquentes de vulnérabilités WordPress publiées.

Qu'est-ce qu'un nonce ? Un nom légèrement trompeur

En cryptographie, un nonce est une valeur utilisée exactement une fois et jamais réutilisée, ce qui la rend utile contre les attaques par rejeu. WordPress a emprunté le nom, mais pas la définition stricte. Un nonce WordPress est une courte empreinte générée à partir de quatre ingrédients : l'action à laquelle il se rattache, l'identifiant et le jeton de session de l'utilisateur courant, la fenêtre temporelle en cours et les clés secrètes de votre wp-config.php. Cette construction a trois conséquences pratiques :

  • Un nonce est personnel. Un jeton généré pour un utilisateur échoue à la validation pour tous les autres, il ne peut donc être ni partagé ni dérobé depuis une page publique.
  • Un nonce est spécifique à une action. Un jeton créé pour l'action delete-post_42 ne vaut rien pour delete-post_43 ni pour aucune autre opération. C'est pourquoi coder en dur un nom d'action générique affaiblit tout le mécanisme.
  • Un nonce est réutilisable pendant sa durée de vie. Le même jeton se valide autant de fois que vous le souhaitez pendant 24 heures. WordPress le documente explicitement, si bien qu'un nonce seul ne protège pas contre le rejeu d'une requête que l'attaquant a déjà capturée.

La documentation officielle pour les développeurs WordPress est d'une franchise rafraîchissante sur tous ces points et décrit les nonces comme une couche de défense, pas comme un système de sécurité complet.

Contre quelles attaques les nonces WordPress protègent-ils ? Le CSRF expliqué

L'attaque qui justifie l'existence des nonces est le cross-site request forgery. Le scénario : vous êtes connecté à votre administration WordPress dans un onglet de navigateur. Dans un autre onglet, vous ouvrez une page sans aucun rapport, contrôlée par un attaquant. Cette page contient un formulaire caché ou une balise image pointant vers votre site, par exemple une requête pour désactiver une extension ou créer un utilisateur. Comme votre navigateur envoie automatiquement vos cookies WordPress à chaque requête vers votre domaine, la requête arrive pleinement authentifiée et WordPress l'exécuterait volontiers. Vous n'avez rien cliqué, vous n'avez rien vu, et votre site vient de gagner un nouvel administrateur.

Les nonces brisent cette attaque à la dernière étape. La page malveillante peut forger la requête, mais elle ne peut pas connaître le nonce courant pour votre utilisateur et cette action, car le jeton n'apparaît que dans les pages que WordPress affiche pour vous. La requête forgée arrive sans nonce valide, la vérification échoue, et WordPress s'arrête sur le fameux écran blanc qui demande : voulez-vous vraiment faire cela ?

Combien de temps un nonce WordPress reste-t-il valide ? Le système d'intervalles

WordPress découpe le temps en intervalles de douze heures. Lors de la vérification d'un nonce, WordPress accepte les jetons de l'intervalle courant et du précédent, d'où la durée de vie maximale de 24 heures. Les fonctions de vérification vous indiquent même dans quelle moitié vous vous trouvez : elles renvoient 1 si le nonce a été généré au cours des douze dernières heures, 2 s'il a entre douze et 24 heures, et false s'il est invalide ou expiré.

La durée de vie se modifie avec le filtre nonce_life, que certaines configurations orientées sécurité utilisent pour réduire la fenêtre :

// Réduire la durée de vie des nonces à 4 heures
add_filter( 'nonce_life', function () {
	return 4 * HOUR_IN_SECONDS;
} );

Des durées plus courtes réduisent la fenêtre de rejeu, mais font aussi expirer plus vite les pages mises en cache contenant des nonces, ce qui pose un vrai problème sur les sites au cache de pages agressif. Si une page en cache sert un nonce vieux de plus de 24 heures, chaque visiteur reçoit un jeton qui ne pourra jamais se valider. C'est la raison classique pour laquelle les fonctionnalités AJAX des sites WordPress fortement mis en cache échouent mystérieusement pour certains visiteurs.

Comment créer un nonce dans WordPress

WordPress fournit trois fonctions d'aide pour générer des nonces, une pour chaque endroit où un jeton se loge habituellement :

// 1. Dans un formulaire : ajoute un champ caché et un champ de référent
wp_nonce_field( 'save_settings_action', 'my_plugin_nonce' );

// 2. Dans une URL : ajoute ?_wpnonce=... à un lien
$url = wp_nonce_url( admin_url( 'admin.php?page=my-plugin&delete=42' ), 'delete-item_42' );

// 3. Jeton brut, par exemple à transmettre à JavaScript
$nonce = wp_create_nonce( 'my_ajax_action' );

Le premier argument est toujours l'action, et c'est là que le soin paye. Une chaîne d'action comme delete-item_42, qui intègre l'identifiant de l'objet, produit un jeton qui ne fonctionne que pour cet élément précis. Une action générique paresseuse comme my_nonce partagée dans toute une extension signifie qu'un seul jeton fuité ou prévisible déverrouille chaque opération offerte par l'extension.

Comment vérifier un nonce : wp_verify_nonce, check_admin_referer et check_ajax_referer

La vérification dispose d'une fonction bas niveau et de deux enrobages pratiques que vous croiserez bien plus souvent dans du vrai code :

// Bas niveau : renvoie 1, 2 ou false, n'interrompt jamais
if ( ! wp_verify_nonce( $_POST['my_plugin_nonce'], 'save_settings_action' ) ) {
	return; // arrêt, requête invalide
}

// Écrans d'administration : vérifie et affiche une page d'erreur en cas d'échec
check_admin_referer( 'save_settings_action', 'my_plugin_nonce' );

// Gestionnaires AJAX : même principe pour les requêtes admin-ajax.php
check_ajax_referer( 'my_ajax_action', 'security' );

Les enrobages interrompent l'exécution en cas d'échec, ce qui est généralement ce que vous voulez en tête d'un gestionnaire. La fonction bas niveau wp_verify_nonce() vous rend la valeur de retour à la place, ce qui vous permet de répondre par une erreur JSON propre dans un contexte d'API. Quelle que soit la variante retenue, la vérification doit intervenir avant l'exécution de l'action, pas après, ce qui paraît évident et reste pourtant un bug récurrent dans les journaux de modifications des extensions.

Les nonces dans la REST API et les requêtes AJAX

La REST API de WordPress utilise le même mécanisme avec un nom d'action fixe. Pour toute requête qui repose sur l'authentification par cookie, WordPress attend un nonce créé pour l'action wp_rest, transmis dans l'en-tête de requête X-WP-Nonce. Les scripts enregistrés de la manière standard l'obtiennent automatiquement : wp_localize_script() ou le paquet plus récent wp.apiFetch transmettent le jeton, et chaque requête REST authentifiée le transporte sans que le développeur ait à y penser.

// Transmettre un nonce REST à votre JavaScript
wp_localize_script( 'my-app', 'myAppData', array(
	'restUrl' => esc_url_raw( rest_url( 'my-plugin/v1/' ) ),
	'nonce'   => wp_create_nonce( 'wp_rest' ),
) );

// En JavaScript : l'envoyer comme en-tête
fetch( myAppData.restUrl + 'items', {
	method: 'POST',
	headers: { 'X-WP-Nonce': myAppData.nonce, 'Content-Type': 'application/json' },
	body: JSON.stringify( { title: 'Nouvel élément' } ),
} );

Sans cet en-tête, la REST API traite la requête comme non authentifiée, même si le navigateur a envoyé des cookies de connexion valides. C'est délibéré : il s'agit exactement de la protection CSRF décrite plus haut, appliquée à l'API.

Pourquoi un nonce n'est pas un contrôle de droits

C'est le point le plus important à comprendre au sujet des nonces, et c'est celui qui dérape régulièrement dans l'écosystème des extensions. Une vérification de nonce réussie prouve deux choses : la requête provient d'une page générée par WordPress, et elle appartient à l'utilisateur à qui le jeton a été délivré. Elle ne prouve pas que cet utilisateur a le droit de faire ce que la requête demande. Un simple abonné peut détenir un nonce parfaitement valide, car WordPress délivre volontiers des nonces à tous les utilisateurs connectés, et certains jetons fonctionnent même pour des visiteurs qui ne sont pas connectés du tout.

Un code de gestionnaire correct pose donc toujours deux questions distinctes :

// Intention : s'agit-il d'une vraie requête de cet utilisateur ?
check_admin_referer( 'save_settings_action', 'my_plugin_nonce' );

// Permission : cet utilisateur a-t-il le droit de faire cela ?
if ( ! current_user_can( 'manage_options' ) ) {
	wp_die( 'Droits insuffisants.' );
}

Les bases de vulnérabilités regorgent de ce qui arrive quand la seconde question est escamotée. Le contrôle d'accès défaillant et le CSRF figurent systématiquement parmi les catégories les plus fréquentes des CVE d'extensions WordPress, et une grande part de ces fiches se résume à un gestionnaire qui a vérifié un nonce, ou rien du tout, au lieu d'un droit. Si vous lisez un avis d'extension qui indique que tout utilisateur authentifié pouvait modifier des réglages, ou qu'une autorisation manquait, c'est en général ce schéma qui se cache derrière.

Les erreurs de nonce courantes dans les thèmes et les extensions

  • Vérification de nonce à la place du contrôle de droits. Le grand classique, décrit ci-dessus. Les deux contrôles sont nécessaires, ils répondent à des questions différentes.
  • Un seul nonce générique pour tout. Une chaîne d'action unique pour toute une extension transforme un jeton étroit en passe-partout.
  • Des nonces dans des pages en cache. Les caches de page complète servent des jetons au-delà de leur durée de vie de 24 heures, cassant silencieusement les formulaires et l'AJAX pour certains visiteurs. La mise en cache par fragments ou la récupération séparée du nonce résout le problème.
  • Vérifier après avoir agi. Le contrôle doit être la toute première chose que fait le gestionnaire.
  • Prendre un nonce pour une preuve d'identité chez les visiteurs déconnectés. Les nonces destinés aux visiteurs sans session sont plus faibles par construction, puisque la composante utilisateur de l'empreinte est vide.
  • Laisser fuir des nonces dans les URL. Les jetons ajoutés aux liens finissent dans les journaux serveur, l'historique du navigateur et l'en-tête Referer. Pour les actions destructrices, les requêtes POST avec wp_nonce_field() sont un meilleur foyer.

Comment InspectWP vous aide à en repérer les conséquences

Vous ne pouvez pas voir de l'extérieur si une extension vérifie correctement ses nonces, mais vous pouvez en voir les conséquences dès qu'elles deviennent publiques. InspectWP détecte les extensions et les thèmes d'un site WordPress analysé ainsi que leurs versions, et les compare aux données de vulnérabilités connues, sachant que les failles de type CSRF et autorisation manquante, exactement celles décrites dans cet article, représentent une large part de ces fiches. Si un rapport signale une extension installée présentant une vulnérabilité publiée, le correctif est presque toujours le même et d'une simplicité rafraîchissante : mettre à jour. Avec des rapports automatiques planifiés, cette boucle détecter, comprendre, mettre à jour tourne en continu au lieu de se déclencher quand quelqu'un y pense.

Vérifiez votre site WordPress dès maintenant

InspectWP analyse votre site WordPress pour détecter les problèmes de sécurité, de SEO, de conformité RGPD et de performance — gratuitement.

Analyser votre site gratuitement