Skip to content

Commit 82f7819

Browse files
Copilotswissspidy
andcommitted
Optimize: check file existence before download and simplify path validation
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
1 parent 78e54f7 commit 82f7819

1 file changed

Lines changed: 16 additions & 16 deletions

File tree

src/WP_CLI/CommandWithUpgrade.php

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -363,23 +363,30 @@ protected function install_from_php_file( $url, $assoc_args ) {
363363
return new WP_Error( 'invalid_filename', 'The sanitized filename does not have a .php extension.' );
364364
}
365365

366+
// Construct destination path.
367+
$dest_path = trailingslashit( WP_PLUGIN_DIR ) . $dest_filename;
368+
369+
// Check if plugin is already installed before downloading.
370+
if ( file_exists( $dest_path ) && ! Utils\get_flag_value( $assoc_args, 'force' ) ) {
371+
return new WP_Error( 'already_installed', 'Plugin already installed.' );
372+
}
373+
366374
// Ensure plugin directory exists.
367375
if ( ! is_dir( WP_PLUGIN_DIR ) ) {
368376
wp_mkdir_p( WP_PLUGIN_DIR );
369377
}
370378

371-
// Validate the destination stays within the plugin directory.
372-
$dest_path = trailingslashit( WP_PLUGIN_DIR ) . $dest_filename;
373-
$real_dest = realpath( WP_PLUGIN_DIR );
374-
$real_path = realpath( dirname( $dest_path ) );
375-
376-
// Ensure plugin directory and destination parent directory are valid.
377-
if ( false === $real_dest || false === $real_path ) {
379+
// Validate the destination stays within the plugin directory (prevent directory traversal).
380+
// Since single-file plugins are installed directly in WP_PLUGIN_DIR, we just need to ensure
381+
// the destination resolves to a file within WP_PLUGIN_DIR.
382+
$real_plugin_dir = realpath( WP_PLUGIN_DIR );
383+
if ( false === $real_plugin_dir ) {
378384
return new WP_Error( 'invalid_path', 'Cannot validate plugin directory path.' );
379385
}
380386

381-
// Ensure destination is within plugin directory (prevent directory traversal).
382-
if ( 0 !== strpos( $real_path, $real_dest ) ) {
387+
// Verify the constructed path is within the plugin directory.
388+
$expected_path = trailingslashit( $real_plugin_dir ) . $dest_filename;
389+
if ( realpath( dirname( $dest_path ) ) !== $real_plugin_dir ) {
383390
return new WP_Error( 'invalid_path', 'The destination path is outside the plugin directory.' );
384391
}
385392

@@ -404,13 +411,6 @@ protected function install_from_php_file( $url, $assoc_args ) {
404411

405412
$plugin_name = $plugin_data['Name'];
406413

407-
// Check if plugin is already installed.
408-
if ( file_exists( $dest_path ) && ! Utils\get_flag_value( $assoc_args, 'force' ) ) {
409-
// Clean up temp file.
410-
unlink( $temp_file );
411-
return new WP_Error( 'already_installed', 'Plugin already installed.' );
412-
}
413-
414414
// Display plugin info.
415415
$version = ! empty( $plugin_data['Version'] ) ? $plugin_data['Version'] : '';
416416
WP_CLI::log( sprintf( 'Installing %s%s', $plugin_name, $version ? " ($version)" : '' ) );

0 commit comments

Comments
 (0)