{"id":350432,"date":"2026-08-19T21:28:48","date_gmt":"2026-08-19T21:28:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/nonce-failure-explainer\/"},"modified":"2026-08-19T22:09:05","modified_gmt":"2026-08-19T22:09:05","slug":"nonce-failure-explainer","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/nonce-failure-explainer\/","author":23544327,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.1","requires":"5.6","requires_php":"7.4","requires_plugins":null,"header_name":"Nonce Failure Explainer","header_author":"Shahzaib Hassan","header_description":"Explains why a WordPress security check failed. Records nonce verification failures with a likely cause, without ever storing the nonce itself.","assets_banners_color":"a593a6","last_updated":"2026-08-19 22:09:05","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/github.com\/shahzaib-hassan-dev","rating":0,"author_block_rating":0,"active_installs":0,"downloads":47,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"shahzaibhassan","date":"2026-08-19 22:09:05"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3655387,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3655387,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3655387,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3655387,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3655387,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3655357,"resolution":"1","location":"assets","locale":"","width":2560,"height":1628}},"screenshots":{"1":"Tools \u2192 Nonce Failures. Each failure carries a confidence level, the specific thing to check\nnext, the request context it came from, and where possible the plugin that ran the check."}},"plugin_section":[],"plugin_tags":[221,2679,2275,11161,600],"plugin_category":[54,59],"plugin_contributors":[276581],"plugin_business_model":[],"class_list":["post-350432","plugin","type-plugin","status-publish","hentry","plugin_tags-ajax","plugin_tags-debugging","plugin_tags-developer","plugin_tags-nonce","plugin_tags-security","plugin_category-security-and-spam-protection","plugin_category-utilities-and-tools","plugin_contributors-shahzaibhassan","plugin_committers-shahzaibhassan"],"banners":{"banner":"https:\/\/ps.w.org\/nonce-failure-explainer\/assets\/banner-772x250.png?rev=3655387","banner_2x":"https:\/\/ps.w.org\/nonce-failure-explainer\/assets\/banner-1544x500.png?rev=3655387","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/nonce-failure-explainer\/assets\/icon.svg?rev=3655387","icon":"https:\/\/ps.w.org\/nonce-failure-explainer\/assets\/icon.svg?rev=3655387","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/nonce-failure-explainer\/assets\/screenshot-1.png?rev=3655357","caption":"Tools \u2192 Nonce Failures. Each failure carries a confidence level, the specific thing to check\nnext, the request context it came from, and where possible the plugin that ran the check."}],"raw_content":"<!--section=description-->\n<p>\"Security check failed\" is an outcome, not a diagnosis. It does not tell you whether the nonce\nfield was missing, the action string differed, the session ended, a cached page served a stale\nvalue, or the nonce simply expired.<\/p>\n\n<p>Nonce Failure Explainer records every failed nonce check and states the most likely cause, along\nwith the specific thing to check next.<\/p>\n\n<h4>What it records<\/h4>\n\n<p>For each failure:<\/p>\n\n<ul>\n<li>The most likely cause, with an explicit confidence level<\/li>\n<li>A concrete next check to run<\/li>\n<li>The nonce action string<\/li>\n<li>The request type (ajax, rest, admin, admin-post, cron, cli, frontend), method, and path<\/li>\n<li>A best-effort guess at which plugin or theme ran the check<\/li>\n<li>Whether the user was logged in<\/li>\n<\/ul>\n\n<h4>What it never records<\/h4>\n\n<ul>\n<li>The nonce value itself<\/li>\n<li>Authentication cookies or session tokens<\/li>\n<li>Passwords, API keys, or any request body<\/li>\n<li>Query strings, which routinely carry one-time tokens<\/li>\n<\/ul>\n\n<p>Function arguments are excluded from the stack trace capture, so sensitive values are never\neven loaded into memory during attribution.<\/p>\n\n<h4>Causes it distinguishes<\/h4>\n\n<ul>\n<li><strong>No nonce was submitted<\/strong> \u2014 the field or query argument never reached the server. Confirmed,\nnot inferred.<\/li>\n<li><strong>The session ended<\/strong> \u2014 an auth cookie arrived but no longer resolves to a user.<\/li>\n<li><strong>A cached page served a stale nonce<\/strong> \u2014 detected when an anonymous request fails while a known\ncaching layer is active.<\/li>\n<li><strong>No session token<\/strong> \u2014 the user is logged in but has no session for the nonce to key against.<\/li>\n<li><strong>Expired or mismatched action<\/strong> \u2014 everything needed was present, so the value itself did not\nmatch.<\/li>\n<\/ul>\n\n<h4>Design<\/h4>\n\n<p>Read-only. The plugin observes and explains; it never alters a request, extends a nonce lifetime,\nor changes site behaviour in any way. Storage is a single non-autoloaded option capped at 200\nevents with a seven-day expiry, so it cannot grow unbounded on a busy site.<\/p>\n\n<p>Nothing is sent anywhere. There is no external service, no telemetry, and no phone-home.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin to <code>\/wp-content\/plugins\/nonce-failure-explainer<\/code>, or install it through the\nPlugins screen.<\/li>\n<li>Activate it.<\/li>\n<li>Reproduce the failing request.<\/li>\n<li>Visit <strong>Tools \u2192 Nonce Failures<\/strong>.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20fix%20nonce%20failures%3F\"><h3>Does this fix nonce failures?<\/h3><\/dt>\n<dd><p>No, and deliberately so. Version 1 is a diagnostic tool. Automatically extending nonce lifetimes\nor bypassing checks would weaken the protection nonces exist to provide.<\/p><\/dd>\n<dt id=\"will%20it%20slow%20my%20site%20down%3F\"><h3>Will it slow my site down?<\/h3><\/dt>\n<dd><p>The recorder only does work when a check actually fails, which on a healthy site is never. There\nis no cost on successful requests.<\/p><\/dd>\n<dt id=\"why%20does%20it%20say%20%22possible%20cause%22%20rather%20than%20telling%20me%20exactly%20what%20happened%3F\"><h3>Why does it say \"possible cause\" rather than telling me exactly what happened?<\/h3><\/dt>\n<dd><p>Because WordPress does not distinguish an expired nonce from one generated for a different action\n\u2014 both simply fail to match. Where the cause can be established as fact, the plugin says\n\"Confirmed\". Where it is inference, it says so.<\/p><\/dd>\n<dt id=\"is%20it%20safe%20on%20a%20production%20site%3F\"><h3>Is it safe on a production site?<\/h3><\/dt>\n<dd><p>Yes. It is read-only, stores no secrets, and caps its own storage. The clearing action is\ncapability-checked and nonce-protected.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20multisite%3F\"><h3>Does it work with multisite?<\/h3><\/dt>\n<dd><p>Yes. The log is per-site, and uninstalling clears it across every site in the network.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Explains why a WordPress security check failed, instead of just telling you that it did.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/350432","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=350432"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/shahzaibhassan"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=350432"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=350432"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=350432"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=350432"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=350432"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=350432"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}