@@ -400,17 +400,29 @@ protected function sqlite_import( $file, $assoc_args ) {
400400 $ contents = str_replace ( 'CREATE UNIQUE INDEX " ' , 'CREATE UNIQUE INDEX IF NOT EXISTS " ' , $ contents );
401401 file_put_contents ( $ import_file , $ contents );
402402
403- $ command = 'sqlite3 ' ;
403+ // Build sqlite3 command as an argument array to avoid shell injection.
404+ $ command = array ( 'sqlite3 ' );
404405
405406 if ( ! Utils \get_flag_value ( $ assoc_args , 'skip-optimization ' ) ) {
406- $ command .= '-cmd "PRAGMA foreign_keys=OFF;" -cmd "PRAGMA ignore_check_constraints=ON;" -cmd "PRAGMA synchronous=OFF;" -cmd "PRAGMA journal_mode=MEMORY;" ' ;
407+ $ command [] = '-cmd ' ;
408+ $ command [] = 'PRAGMA foreign_keys=OFF; ' ;
409+ $ command [] = '-cmd ' ;
410+ $ command [] = 'PRAGMA ignore_check_constraints=ON; ' ;
411+ $ command [] = '-cmd ' ;
412+ $ command [] = 'PRAGMA synchronous=OFF; ' ;
413+ $ command [] = '-cmd ' ;
414+ $ command [] = 'PRAGMA journal_mode=MEMORY; ' ;
407415 }
408416
409- $ command .= "$ db_path < $ import_file " ;
417+ // Add database path as final argument.
418+ $ command [] = $ db_path ;
410419
411- WP_CLI ::debug ( "Running shell command: {$ command }" , 'db ' );
420+ // For debugging, show a safely escaped shell-like representation.
421+ $ debug_command = implode ( ' ' , array_map ( 'escapeshellarg ' , $ command ) );
422+ WP_CLI ::debug ( "Running shell command: {$ debug_command }" , 'db ' );
412423
413- $ result = \WP_CLI \Process::create ( $ command , null , null )->run ();
424+ // Pass the SQL contents via stdin instead of using shell redirection.
425+ $ result = \WP_CLI \Process::create ( $ command , null , null , null , array ( 'stdin ' => $ contents ) )->run ();
414426
415427 if ( 0 !== $ result ->return_code ) {
416428 WP_CLI ::error ( 'Could not import database. ' );
0 commit comments