Het woord komt van het Engelse "number used once". In de cryptografie omschrijft MDN het als een willekeurige waarde die maar een keer in een communicatie wordt gebruikt, om te voorkomen dat een onderschept bericht opnieuw wordt afgespeeld, om te garanderen dat een antwoord vers is of om toeval toe te voegen aan een berekening. Op het web dekt de term echter twee nogal verschillende zaken, die je beter niet door elkaar haalt: de "zuivere" cryptografische nonce en de nonce van WordPress.
Waar nonces op het web voor dienen
- In protocollen: de uitwisselingen van TLS en veel authenticatiemechanismen bevatten eenmalige willekeurige waarden, zodat een opgenomen gesprek niet ongewijzigd kan worden afgespeeld.
- In een Content Security Policy: de server maakt bij elk antwoord een willekeurige waarde aan en zet die in de directive
script-src 'nonce-...'en in het attribuutnoncevan de toegestane scripts. Een strikte CSP voert alleen scripts uit die de juiste waarde dragen. MDN benadrukt dat die waarde bij elk antwoord moet veranderen en onvoorspelbaar moet blijven. - Tegen vervalste verzoeken: een geheim token in formulieren bewijst dat het verzoek echt van een pagina van de site komt, wat CSRF-aanvallen tegenhoudt. Dat is de belangrijkste rol van WordPress-nonces.
WordPress-nonces: niet echt nonces
De officiële documentatie van WordPress geeft het zelf toe: zijn nonces zijn geen getallen en ook niet eenmalig. De functie wp_create_nonce() berekent een hash van tien tekens op basis van de gevraagde actie, het ID van de gebruiker, zijn sessietoken en een tijdsperiode. Daarbij worden de sleutels NONCE_KEY en NONCE_SALT uit wp-config.php gebruikt, en daarom is een unieke salt belangrijk.
- Levensduur: standaard een dag, verdeeld in twee periodes van 12 uur. Afhankelijk van het moment waarop hij is aangemaakt, blijft een nonce dus 12 tot 24 uur geldig. Het filter
nonce_lifepast die duur aan. - Herbruikbaar: WordPress controleert niet of een nonce maar een keer is gebruikt. Binnen de geldigheidsduur beschermt hij dus niet tegen herhaling.
- Niet-ingelogde bezoekers: hun ID is 0, waardoor alle anonieme bezoekers voor dezelfde actie dezelfde nonce kunnen krijgen.

Voor WordPress: nonces goed gebruiken
Voor een ontwikkelaar van thema's of plugins komt de regel neer op drie functies en een rechtencontrole:
// In het formulier
wp_nonce_field( 'verwijder_post_' . $post_id );
// Bij de verwerking
check_admin_referer( 'verwijder_post_' . $post_id );
if ( ! current_user_can( 'delete_post', $post_id ) ) {
wp_die( 'Actie niet toegestaan.' );
}
check_admin_referer()controleert de nonce en de referer op beheerschermen,check_ajax_referer()alleen de nonce voor AJAX-verzoeken,wp_verify_nonce()in de overige gevallen.- Geef de actie een precieze naam (met het ID van het object) in plaats van een algemene naam die de hele site deelt.
- Vertrouw voor autorisatie nooit op de nonce: de documentatie vraagt om elke functie te beschermen met
current_user_can().
Veelgemaakte fouten
Een flink deel van de pluginlekken die elk jaar worden gemeld, komt door een ontbrekende nonce of een vergeten capability-controle, zoals ons artikel over WordPress-pluginlekken in cijfers laat zien. Het typische geval: een AJAX-actie controleert de nonce, maar niet het recht van de gebruiker. Een nonce kan echter uitlekken in de code van een openbare pagina; is hij de enige drempel, dan kan een gewone abonnee soms een beheerdersactie uitvoeren, wat leidt tot privilege-escalatie. Onze gids over rollen en capabilities in WordPress legt het principe van minimale rechten uit.
Nog een valkuil: een pagina die langer dan 12 tot 24 uur in de cache staat, serveert een verlopen nonce, en het formulier mislukt dan met de melding dat de gevolgde link verlopen is (in het Engels "The link you followed has expired"). Sluit pagina's met formulieren voor ingelogde gebruikers uit van de cache.