#793·shell_gpt

Function-calling feature executes LLM-proposed shell commands with no confirmation, unlike the tool's own --shell mode

Author: carfeiiCreated Aug 5, 2026Updated Aug 5, 2026

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.