[wp-trac] [WordPress Trac] #65052: Nonce check order flaw in post-quickdraft-save

WordPress Trac noreply at wordpress.org
Thu Apr 23 03:40:23 UTC 2026


#65052: Nonce check order flaw in post-quickdraft-save
-------------------------------------+------------------------------
 Reporter:  rajeshcp                 |       Owner:  rajeshcp
     Type:  defect (bug)             |      Status:  assigned
 Priority:  normal                   |   Milestone:  Awaiting Review
Component:  Security                 |     Version:  trunk
 Severity:  normal                   |  Resolution:
 Keywords:  has-patch needs-testing  |     Focuses:
-------------------------------------+------------------------------

Comment (by liaison):

 Test Report for Ticket #65052
 Environment
 OS: Windows (XAMPP)

 PHP: 8.2.x

 WordPress: 7.1-alpha (trunk)

 Testing Area: Dashboard Quick Draft (wp-admin/post.php)

 The Problem
 In the original code, the resource (Post object) is fetched via get_post()
 before the Nonce is verified or the Post ID is validated. This leads to:

 Unnecessary Database Lookups: Database is queried even if the request is
 unauthorized.

 PHP Warnings: In PHP 8.2+, providing a non-existent post_ID leads to a
 Fatal-level Warning when attempting to access properties on a null object
 later in the execution flow.

 Test Results (Before Patch)

 Test 1 valid nonce & valid post id:
 {{{
 jQuery.post( ajaxurl.replace('admin-ajax.php', 'post.php'), {
     action: 'post-quickdraft-save',
     _wpnonce: 'valid_nonce_here', // valid nonce
     post_ID: 1 // valid id
 });
 }}}
 Test 1 result:
 [23-Apr-2026 03:02:52 UTC] DEBUG: get_post() was called for ID: 1

 Test 2 invalid nonce & valid post id:
 {{{
 jQuery.post( ajaxurl.replace('admin-ajax.php', 'post.php'), {
     action: 'post-quickdraft-save',
     _wpnonce: 'wrong_nonce_here', // wrong_nonce
     post_ID: 1 // valid id
 });
 }}}
 Test 2 result:
 [23-Apr-2026 03:02:58 UTC] error_msg: Unable to submit this form, please
 refresh and try again.

 Test 3 valid nonce & invalid post id:
 {{{
 jQuery.post( ajaxurl.replace('admin-ajax.php', 'post.php'), {
     action: 'post-quickdraft-save',
     _wpnonce: 'valid_nonce_here', // valid nonce
     post_ID: 999999 // invalid id
 });
 }}}
 Test 3 result:
 [23-Apr-2026 03:03:53 UTC] DEBUG: get_post() was called for ID: 999999
 [23-Apr-2026 03:03:53 UTC] PHP Warning:  Attempt to read property
 "post_type" on null in C:\xampp\htdocs\wp-core\src\wp-admin\post.php on
 line 103

 Suggested patch
 {{{#!php
 <?php
         case 'post-quickdraft-save':
                 // Check nonce and capabilities.
                 $nonce     = $_REQUEST['_wpnonce'];
                 // patch-ticket: 65052-begin
                 $post_id = absint( $_REQUEST['post_ID'] ?? 0 );
                 $post    = $post_id ? get_post( $post_id ) : null;
                 // patch-ticket: 65052-end
                 $error_msg = false;

                 // For output of the Quick Draft dashboard widget.
                 require_once ABSPATH . 'wp-admin/includes/dashboard.php';

                 if ( ! $post || ! wp_verify_nonce( $nonce, 'add-post' ) )
 {
                         $error_msg = __( 'Unable to submit this form,
 please refresh and try again.' );
                 }

                 if ( ! current_user_can( get_post_type_object( 'post'
 )->cap->create_posts ) ) {
                         exit;
                 }

                 if ( $error_msg ) {
                         //check ticket: 65052 Nonce check order flaw in
 post-quickdraft-save
                         //error_log( "error_msg: " . ($error_msg ??
 'none') );
                         return wp_dashboard_quick_press( $error_msg );
                 }

                 //check ticket: 65052 Nonce check order flaw in post-
 quickdraft-save
                 //error_log( "DEBUG: get_post() was called for ID: " .
 ($_REQUEST['post_ID'] ?? 'none') );
                 check_admin_referer( 'add-' . $post->post_type );

 }}}

 Test Results (After Patch)
 Test 3 valid nonce & invalid post id:
 {{{
 jQuery.post( ajaxurl.replace('admin-ajax.php', 'post.php'), {
     action: 'post-quickdraft-save',
     _wpnonce: 'valid_nonce_here', // valid nonce
     post_ID: 999999 // invalid id
 });
 }}}
 Test 3 result:
 [23-Apr-2026 03:07:42 UTC] error_msg: Unable to submit this form, please
 refresh and try again.

 Verdict
 The optimized patch addresses the security flaw and improves system
 reliability for PHP 8.2+ environments.

 Summary
 Strict Validation. Ensuring that get_post() is handled safely by using
 absint() and a ternary check for $post.

 Logic Ordering. Nonce and resource existence are verified immediately.

 Stability. Preventing the attempt to read property on null warning in PHP
 8.2, which was previously triggered by a valid nonce but an invalid ID.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/65052#comment:5>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list