From d9e188a2f6df4e594df6ae48456ba01890e2415c Mon Sep 17 00:00:00 2001 From: corsac Date: Fri, 23 Oct 2026 16:26:48 +0100 Subject: [PATCH] Security: Require a nonce-protected POST to delete a custom role (GO-54) The delete confirm step was a GET link, so any page could delete a custom role by sending an admin to ?action=delete&role=&confirm=1. The confirm view now posts a form carrying a role_delete_ nonce, and the handler only deletes after verifying it; a GET or a bad nonce shows the confirm view. --- dt-core/admin/menu/tabs/tab-custom-roles.php | 26 ++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/dt-core/admin/menu/tabs/tab-custom-roles.php b/dt-core/admin/menu/tabs/tab-custom-roles.php index da9d120a97..41fbecd6d4 100644 --- a/dt-core/admin/menu/tabs/tab-custom-roles.php +++ b/dt-core/admin/menu/tabs/tab-custom-roles.php @@ -152,7 +152,14 @@ private function delete_action() { return; } - if ( !isset( $_GET['confirm'] ) ) { + if ( !isset( $_POST['role_delete_nonce'] ) ) { + $this->view_delete(); + return; + } + + $slug = sanitize_text_field( wp_unslash( $_GET['role'] ) ); + if ( !wp_verify_nonce( sanitize_key( $_POST['role_delete_nonce'] ), 'role_delete_' . $slug ) ) { + $this->show_error( new WP_Error( 401, __( 'Unauthorized', 'disciple_tools' ) ) ); $this->view_delete(); return; } @@ -841,12 +848,17 @@ class="button button-large" > - - - +
+ + +