Skip to content

Commit cb28ab0

Browse files
CopilotswissspidyCopilot
authored
Prefer /bin/bash and validate SHELL points to bash before using it (#81)
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Pascal Birchler <pascal.birchler@gmail.com> Co-authored-by: Pascal Birchler <pascalb@google.com>
1 parent da90953 commit cb28ab0

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

features/shell.feature

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,38 @@ Feature: WordPress REPL
6161
"""
6262
And STDERR should be empty
6363
64+
Scenario: Use SHELL environment variable as fallback for bash
65+
Given a WP install
66+
67+
And a session file:
68+
"""
69+
return true;
70+
"""
71+
72+
# SHELL pointing to bash should work (when bash is available).
73+
When I try `SHELL=/bin/bash wp shell --basic < session`
74+
Then STDOUT should contain:
75+
"""
76+
bool(true)
77+
"""
78+
And STDERR should be empty
79+
80+
# SHELL pointing to non-bash binary should be ignored and fall back to /bin/bash.
81+
When I try `SHELL=/bin/sh wp shell --basic < session`
82+
Then STDOUT should contain:
83+
"""
84+
bool(true)
85+
"""
86+
And STDERR should be empty
87+
88+
# SHELL pointing to invalid path should be ignored and fall back to /bin/bash.
89+
When I try `SHELL=/nonsense/path wp shell --basic < session`
90+
Then STDOUT should contain:
91+
"""
92+
bool(true)
93+
"""
94+
And STDERR should be empty
95+
6496
Scenario: Input starting with dash
6597
Given a WP install
6698
And a session file:

src/WP_CLI/Shell/REPL.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,15 @@ private static function create_prompt_cmd( $prompt, $history_path ) {
122122
$history_path = escapeshellarg( $history_path );
123123
if ( getenv( 'WP_CLI_CUSTOM_SHELL' ) ) {
124124
$shell_binary = (string) getenv( 'WP_CLI_CUSTOM_SHELL' );
125-
} else {
125+
} elseif ( is_file( '/bin/bash' ) && is_readable( '/bin/bash' ) ) {
126+
// Prefer /bin/bash when available since we use bash-specific commands.
126127
$shell_binary = '/bin/bash';
128+
} elseif ( getenv( 'SHELL' ) && self::is_bash_shell( (string) getenv( 'SHELL' ) ) ) {
129+
// Only use SHELL as fallback if it's bash (we use bash-specific commands).
130+
$shell_binary = (string) getenv( 'SHELL' );
131+
} else {
132+
// Final fallback for systems without /bin/bash.
133+
$shell_binary = 'bash';
127134
}
128135

129136
if ( ! is_file( $shell_binary ) || ! is_readable( $shell_binary ) ) {
@@ -144,6 +151,21 @@ private static function create_prompt_cmd( $prompt, $history_path ) {
144151
return "{$shell_binary} -c " . escapeshellarg( $cmd );
145152
}
146153

154+
/**
155+
* Check if a shell binary is bash or bash-compatible.
156+
*
157+
* @param string $shell_path Path to the shell binary.
158+
* @return bool True if the shell is bash, false otherwise.
159+
*/
160+
private static function is_bash_shell( $shell_path ) {
161+
if ( ! is_file( $shell_path ) || ! is_readable( $shell_path ) ) {
162+
return false;
163+
}
164+
// Check if the basename is exactly 'bash' or starts with 'bash' followed by a version/variant.
165+
$basename = basename( $shell_path );
166+
return 'bash' === $basename || 0 === strpos( $basename, 'bash-' );
167+
}
168+
147169
private function set_history_file() {
148170
$data = getcwd() . get_current_user();
149171

0 commit comments

Comments
 (0)