Safeguard
Security Guides•

WordPress nonces are not authorization: check capabilities too

A WordPress nonce helps against CSRF, lasts 12 to 24 hours and is not one time. Why plugin code must also check current_user_can() for every action.

Safeguard Security Team
Updated 3 min read

A WordPress nonce is a token that helps protect forms and URLs against CSRF. It is not a one-time number, it lasts between 12 and 24 hours by default, and the developer handbook says it should never be relied on for authentication, authorization or access control. Check current_user_can() as well.

What a nonce is

Despite the name, the handbook says a WordPress nonce is a hash of letters and numbers, not a true number used once. WordPress does not check one-time use, so a captured nonce can be replayed while it is valid. Nonces defend against forged requests, where a third party site tricks a logged in user's browser into submitting something.

Lifetime

By default a nonce is valid for one day. WordPress uses two time windows, each half the lifetime, so a nonce stays valid for between 12 and 24 hours. The nonce_life filter changes it and takes seconds.

The functions

  • wp_create_nonce( $action ): Returns a nonce string for custom contexts
  • wp_nonce_field( $action ): Prints hidden form fields with the nonce and referrer
  • check_admin_referer( $action ): Verifies nonce and referrer on admin forms, ends with 403 on failure
  • wp_verify_nonce( $nonce, $action ): Verifies in any context and returns a result
  • check_ajax_referer( $action ): Verifies for AJAX, checks the nonce but not the referrer

The pairing that matters

A nonce answers "did this request come from a page we served to this browser". It does not answer "is this user allowed to do this". The handbook tells you to also check permissions with current_user_can().

check_admin_referer( 'myplugin_delete' );
if ( ! current_user_can( 'manage_options' ) ) {
    wp_die( 'Not allowed.' );
}

A plugin that checks only a nonce can be abused by any logged in user who can obtain a valid one, for example a subscriber account who loads a page that prints it.

Review habits

  1. Every state changing handler checks a nonce and a capability.
  2. AJAX handlers use check_ajax_referer and a capability check.
  3. Capabilities are specific, not just "is logged in".
  4. Nonces are never used as secrets or access tokens.

Quick check

Can a nonce be used once only?

No. The handbook says WordPress does not check for one-time use, so a nonce can be reused while valid.

Is nonce check plus login check enough?

Check a specific capability with current_user_can(). Being logged in does not mean being allowed.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.