@@ -183,11 +183,15 @@ function export_wp( $args = array() ) {
183183 )
184184 );
185185
186+ // Cast thumbnail IDs to integers to prevent second-order SQL injection via user-controlled meta values.
187+ $ thumbnails_ids = array_filter ( array_map ( 'absint ' , $ thumbnails_ids ) );
188+
186189 $ additional_ids = array_merge ( $ additional_ids , $ attachment_ids , $ thumbnails_ids );
187190 }
188191
189- // Merge the additional IDs back with the original post IDs after processing all posts
190- $ post_ids = array_unique ( array_merge ( $ post_ids , $ additional_ids ) );
192+ // Merge the additional IDs back with the original post IDs after processing all posts.
193+ // Cast to integers as defense-in-depth, since $additional_ids may include values sourced from postmeta.
194+ $ post_ids = array_unique ( array_map ( 'absint ' , array_merge ( $ post_ids , $ additional_ids ) ) );
191195 }
192196
193197 /*
@@ -597,8 +601,10 @@ function wxr_filter_postmeta( $return_me, $meta_key ) {
597601
598602 // Fetch 20 posts at a time rather than loading the entire table into memory.
599603 while ( $ next_posts = array_splice ( $ post_ids , 0 , 20 ) ) {
600- $ where = 'WHERE ID IN ( ' . implode ( ', ' , $ next_posts ) . ') ' ;
601- $ posts = $ wpdb ->get_results ( "SELECT * FROM {$ wpdb ->posts } $ where " );
604+ // Re-sanitize immediately before use, as defense-in-depth against the IDs being interpolated directly into SQL below.
605+ $ next_posts = array_map ( 'absint ' , $ next_posts );
606+ $ where = 'WHERE ID IN ( ' . implode ( ', ' , $ next_posts ) . ') ' ;
607+ $ posts = $ wpdb ->get_results ( "SELECT * FROM {$ wpdb ->posts } $ where " );
602608
603609 // Begin Loop.
604610 foreach ( $ posts as $ post ) {
0 commit comments