Function-calling feature executes LLM-proposed shell commands with no confirmation, unlike the tool's own --shell mode
Summary
shell_gpt's function-calling feature (enabled by default via
OPENAI_USE_FUNCTIONS=true) lets the model autonomously invoke
execute_shell_command, which runs its argument via
subprocess.Popen(shell_command, shell=True, ...)
(sgpt/llm_functions/common/execute_shell.py). In
Handler.handle_function_call (sgpt/handlers/handler.py), once a tool-call
response names this function, it runs immediately: the only output is a
one-line notice of the call, and by default configuration
(SHOW_FUNCTIONS_OUTPUT=false) not even the command's output is shown.
There is no confirmation prompt.
This is a direct contrast with the tool's own --shell mode, which correctly shows an "[E]xecute, [M]odify, [D]escribe, [A]bort" prompt before running an LLM-proposed command (sgpt/app.py). Function-calling and --shell mode are mutually exclusive in this codebase (Handler.get_completion explicitly disables functions for the shell/code/describe-shell roles), so the codebase clearly demonstrates awareness of the need for confirmation on one path while the parallel function-calling path has none.
Piping untrusted content into sgpt is the tool's own advertised primary
workflow (the README's examples include git diff | sgpt "...", docker logs -n 20 my_app | sgpt "...", and cat file.py | sgpt --code "...").
Any such content is a route for a prompt-injection payload to reach the
model's context; if the model is induced to call execute_shell_command,
the resulting command runs immediately with no chance to review or
decline.
Validated against 1.5.1.
POC
(available upon request)
Impact
Driving the unmodified Handler.handle_function_call with a crafted tool-call payload naming execute_shell_command (no live API call required, since the method only processes an already-received tool call) executed a marker shell command immediately, with the only output being a one-line notice, confirming there is no confirmation step of any kind before a function-call-derived shell command runs. Getting a model to reliably emit such a call from injected content was not itself tested, since that depends on the specific model/technique and is outside shell_gpt's control; what is confirmed is that shell_gpt itself provides no safeguard once such a call exists.
Suggested Fix
Require the same explicit confirmation for function-call-originated shell commands that --shell mode already requires for its own LLM-proposed commands, before calling Function.execute in handle_function_call.
Source: TheR1D/shell_gpt