The earlier Escaping & Sanitizing lesson covered making output safe. A nonce ("number used once") covers the other direction — verifying an incoming form submission or action request genuinely came from a page your site rendered, not a forged request from elsewhere.
Without one, a malicious site could trick a logged-in user's browser into submitting a request to your site — the browser sends the session cookie automatically, making the forged request look legitimate. This is the same CSRF attack covered in the PHP Security lesson; a nonce is WordPress's specific built-in defense against it.
<form method="post" action="">
<?php wp_nonce_field('wgh_save_settings', 'wgh_nonce'); ?>
<input type="text" name="site_tagline">
<button type="submit">Save</button>
</form>wp_nonce_field() outputs a hidden input containing a token tied to the current user's session and the action name given as its first argument.
if (isset($_POST['wgh_nonce']) && wp_verify_nonce($_POST['wgh_nonce'], 'wgh_save_settings')) {
// Safe to process the form
update_option('site_tagline', sanitize_text_field($_POST['site_tagline']));
} else {
wp_die('Security check failed.');
}The same idea applies to a plain link that triggers an action (deleting an item, for example), not just a form.
<?php $url = wp_nonce_url(admin_url('admin-post.php?action=wgh_delete_item&id=42'), 'wgh_delete_item_42'); ?>
<a href="<?php echo esc_url($url); ?>">Delete</a>// Handling it
if (!isset($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'wgh_delete_item_' . $_GET['id'])) {
wp_die('Security check failed.');
}What a nonce is not
A nonce expires (24 hours by default) and is tied to the specific user session that generated it — it isn't a password or a secret to keep hidden, just a check that the request came from where it claims to.