Follow-up from #433 (#429). Pre-existing, severable, and deliberately left out of the release fix.
What
In Challenge::build_replay_response_data():
$neutral_url = is_network_admin() ? network_admin_url() : admin_url();
Both replay_stash() call sites are inside Challenge::handle_ajax_auth() and Challenge::handle_ajax_2fa(), registered as wp_ajax_*. So this runs under wp-admin/admin-ajax.php, which never calls set_current_screen() and does not define WP_NETWORK_ADMIN. is_network_admin() reads $GLOBALS['current_screen'], then WP_NETWORK_ADMIN, then returns false — so it is always false here, even for a genuine network action.
Consequence: a refused network-admin action lands on the site dashboard rather than the network dashboard.
Why it was not fixed in #433
The notice still renders. render_blocked_replay_notice() is hooked to both admin_notices and network_admin_notices, and the site dashboard fires admin_notices — so the user gets the explanation, just on the wrong dashboard. A wrong-dashboard wart, not a lost explanation, and unrelated to what #429 reported.
The #433 handler classification originally also keyed on is_network_admin(), which made it dead code; that was fixed there by deciding from the URL path instead. Nothing in the classification path consults request context any more, so this is now the only remaining consumer and it is severable.
Fix
Derive the same way the handler check does — from the stashed URL's path — or thread the surface through from the caller. Worth a look at whether any other is_network_admin() / is_multisite() call reachable from the ajax handlers has the same problem; two instances of this exact fault were found during #433 review, plus one in a test.
Related
Follow-up from #433 (#429). Pre-existing, severable, and deliberately left out of the release fix.
What
In
Challenge::build_replay_response_data():Both
replay_stash()call sites are insideChallenge::handle_ajax_auth()andChallenge::handle_ajax_2fa(), registered aswp_ajax_*. So this runs underwp-admin/admin-ajax.php, which never callsset_current_screen()and does not defineWP_NETWORK_ADMIN.is_network_admin()reads$GLOBALS['current_screen'], thenWP_NETWORK_ADMIN, then returnsfalse— so it is always false here, even for a genuine network action.Consequence: a refused network-admin action lands on the site dashboard rather than the network dashboard.
Why it was not fixed in #433
The notice still renders.
render_blocked_replay_notice()is hooked to bothadmin_noticesandnetwork_admin_notices, and the site dashboard firesadmin_notices— so the user gets the explanation, just on the wrong dashboard. A wrong-dashboard wart, not a lost explanation, and unrelated to what #429 reported.The #433 handler classification originally also keyed on
is_network_admin(), which made it dead code; that was fixed there by deciding from the URL path instead. Nothing in the classification path consults request context any more, so this is now the only remaining consumer and it is severable.Fix
Derive the same way the handler check does — from the stashed URL's path — or thread the surface through from the caller. Worth a look at whether any other
is_network_admin()/is_multisite()call reachable from the ajax handlers has the same problem; two instances of this exact fault were found during #433 review, plus one in a test.Related