Conversation
The notifications module was incorrectly checking the generic `_wpnonce` field against Edit Flow's expected action when posts were saved. This caused contact forms and other plugins that triggered post status transitions to fail, as Edit Flow would call `wp_die()` when their unrelated nonces didn't verify against Edit Flow's action. The fix ensures Edit Flow only processes its own form submissions by checking for the presence of `ef-save_followers` before performing any nonce verification. When Edit Flow's form is submitted, it now verifies against its own dedicated `ef_notifications_nonce` field with the `save_user_usergroups` action, rather than checking the generic `_wpnonce` that other forms might use. Additionally, the AJAX handler `handle_user_post_subscription()` had a security vulnerability where requests without any nonce would pass through due to faulty logic (`!empty && !verify` instead of `empty || !verify`). This has been corrected to properly require a valid nonce. The changes also improve error handling by returning early instead of calling `wp_die()` in the `save_post_subscriptions()` hook. This prevents Edit Flow from terminating requests during the `transition_post_status` action, which fires for all post changes regardless of context. Fixes #882 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@GaryJones A quick visual review seems good to me. However, I'm questioning if this is correct:
I think it might be better if that was hooked onto the save_post action instead of the transition. |
|
Thanks for the review @dd32! The That said, your instinct is sound — |
Summary
Fixes #882
The notifications module was incorrectly checking the generic
_wpnoncefield against Edit Flow's expected action when posts were saved. This caused contact forms and other plugins that triggered post status transitions to fail, as Edit Flow would callwp_die()when their unrelated nonces didn't verify.Changes
save_post_subscriptions(): Now checks for Edit Flow's own form indicator (ef-save_followers) first, then verifies its own dedicated nonce field (ef_notifications_nonce) with actionsave_user_usergroups. Returns early instead of callingwp_die().handle_user_post_subscription(): Fixed faulty nonce logic that allowed requests without any nonce to pass through. Changed from! empty() && ! verify()to! isset() || ! verify().Walkthrough: How this fixes the reported issue
The Scenario
A user submits a speaker contact form on WordCamp. This form:
$_POST['_wpnonce']field for actionspeaker_submissiontransition_post_statushookBefore (The Bug)
What happened:
$_POST['_wpnonce']= nonce forspeaker_submissiontransition_post_statusfires →save_post_subscriptions()runs! empty( $_POST['_wpnonce'] )→ TRUE (the contact form set it)! wp_verify_nonce( $_POST['_wpnonce'], 'update-post_123' )→ TRUE (wrong action, verification fails)print_ajax_response()→wp_die()→ Request killedAfter (The Fix)
What happens now:
$_POST['_wpnonce']= nonce forspeaker_submissiontransition_post_statusfires →save_post_subscriptions()runs! isset( $_POST['ef-save_followers'] )→ TRUE (contact form didn't set this)Key changes
ef-save_followers) before doing anythingef_notifications_nonce) instead of the generic_wpnonceTest plan
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com