Skip to content

Commit 4bdfc26

Browse files
Andrew Bakerclaude
andcommitted
Fix 3 remaining MEDIUM security issues
- is_safe_query(): strip all block comments (incl. mid-query /*!...*/ hints) and line comments before keyword/denylist checks - ajax_scan/preview/migrate_single/migrate_all: move current_user_can() before check_ajax_referer() (capability-first pattern) - ajax_migrate_single/migrate_all: esc_html() on post_title in JSON response messages Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 509ce16 commit 4bdfc26

File tree

1 file changed

+22
-20
lines changed

1 file changed

+22
-20
lines changed

cs-code-block.php

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -917,8 +917,10 @@ private static function render_sql_panel() {
917917
*/
918918
private static function is_safe_query( string $sql ): bool {
919919
$clean = trim( $sql );
920-
// Strip leading block and line comments before keyword check.
921-
$clean = preg_replace( '/^(\/\*.*?\*\/\s*|--[^\n]*\n\s*|#[^\n]*\n\s*)*/s', '', $clean );
920+
// Strip all block comments (including mid-query MySQL /*!...*/ optimizer hints),
921+
// line comments (-- and #), and surrounding whitespace before keyword check.
922+
$clean = preg_replace( '/\/\*.*?\*\//s', '', $clean );
923+
$clean = preg_replace( '/(--|#)[^\n]*/m', '', $clean );
922924
$clean = trim( $clean );
923925
// Reject any query containing a semicolon — prevents statement stacking
924926
// (e.g. SELECT 1; DROP TABLE wp_users).
@@ -1238,14 +1240,14 @@ private static function get_migration_preview( $content ) {
12381240
* @return void Sends JSON response and exits.
12391241
*/
12401242
public static function ajax_scan() {
1241-
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1242-
wp_send_json_error( 'Bad nonce', 403 );
1243-
}
1244-
12451243
if ( ! current_user_can( 'manage_options' ) ) {
12461244
wp_send_json_error( 'Forbidden', 403 );
12471245
}
12481246

1247+
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1248+
wp_send_json_error( 'Bad nonce', 403 );
1249+
}
1250+
12491251
global $wpdb;
12501252

12511253
// Static query — no user data; $wpdb->posts is a trusted WP core property.
@@ -1294,14 +1296,14 @@ public static function ajax_scan() {
12941296
* @return void Sends JSON response and exits.
12951297
*/
12961298
public static function ajax_preview() {
1297-
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1298-
wp_send_json_error( 'Bad nonce', 403 );
1299-
}
1300-
13011299
if ( ! current_user_can( 'manage_options' ) ) {
13021300
wp_send_json_error( 'Forbidden', 403 );
13031301
}
13041302

1303+
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1304+
wp_send_json_error( 'Bad nonce', 403 );
1305+
}
1306+
13051307
$post_id = (int) ( $_POST['post_id'] ?? 0 );
13061308
$post = get_post( $post_id );
13071309

@@ -1326,14 +1328,14 @@ public static function ajax_preview() {
13261328
* @return void Sends JSON response and exits.
13271329
*/
13281330
public static function ajax_migrate_single() {
1329-
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1330-
wp_send_json_error( 'Bad nonce', 403 );
1331-
}
1332-
13331331
if ( ! current_user_can( 'manage_options' ) ) {
13341332
wp_send_json_error( 'Forbidden', 403 );
13351333
}
13361334

1335+
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1336+
wp_send_json_error( 'Bad nonce', 403 );
1337+
}
1338+
13371339
$post_id = (int) ( $_POST['post_id'] ?? 0 );
13381340
$post = get_post( $post_id );
13391341

@@ -1361,7 +1363,7 @@ public static function ajax_migrate_single() {
13611363
wp_send_json_success( [
13621364
'post_id' => $post_id,
13631365
'blocks_migrated' => $count,
1364-
'message' => "Migrated {$count} block(s) in \"{$post->post_title}\".",
1366+
'message' => 'Migrated ' . $count . ' block(s) in "' . esc_html( $post->post_title ) . '".',
13651367
] );
13661368
}
13671369

@@ -1372,14 +1374,14 @@ public static function ajax_migrate_single() {
13721374
* @return void Sends JSON response and exits.
13731375
*/
13741376
public static function ajax_migrate_all() {
1375-
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1376-
wp_send_json_error( 'Bad nonce', 403 );
1377-
}
1378-
13791377
if ( ! current_user_can( 'manage_options' ) ) {
13801378
wp_send_json_error( 'Forbidden', 403 );
13811379
}
13821380

1381+
if ( ! check_ajax_referer( self::MIGRATE_NONCE, 'nonce', false ) ) {
1382+
wp_send_json_error( 'Bad nonce', 403 );
1383+
}
1384+
13831385
global $wpdb;
13841386

13851387
// Static query — no user data; $wpdb->posts is a trusted WP core property.
@@ -1422,7 +1424,7 @@ public static function ajax_migrate_all() {
14221424

14231425
$migrated_posts++;
14241426
$migrated_blocks += $count;
1425-
$details[] = "#{$post->ID}: {$post->post_title} ({$count} blocks)";
1427+
$details[] = '#' . $post->ID . ': ' . esc_html( $post->post_title ) . ' (' . $count . ' blocks)';
14261428
}
14271429
}
14281430

0 commit comments

Comments
 (0)