Fix command injection in Custom Command#1363
Open
codingfrog wants to merge 1 commit into
Open
Conversation
Replace shell=True subprocess calls with properly tokenized arguments using shlex.split() and shell=False. This prevents command injection when file paths contain shell metacharacters. - Use shlex.split() to tokenize custom command string - Replace %d/%r placeholders in tokenized arguments - Execute with shell=False for security - Add error handling with user feedback - Remove Windows quoted-path workaround (unnecessary with shell=False) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
glubsy
approved these changes
Feb 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
During a security audit of dupeGuru, we identified a command injection vulnerability in the Custom Command feature.
Vulnerability
The code at
core/app.pyininvoke_custom_command()constructs a shell command by performing string substitution on the user's custom command template, replacing%dand%rwith file paths, then passes the resulting string tosubprocess.Popen()withshell=True:Because
shell=Truepasses the entire string to the system shell for interpretation, any shell metacharacters in file paths are evaluated. A file named$(rm -rf ~).txtwould cause arbitrary command execution when the user invokes a custom command on it.The existing Windows workaround (wrapping paths in quotes) is insufficient — it doesn't handle all injection vectors and doesn't protect Unix/macOS at all.
Attack scenario
Fix
shlex.split(cmd)to tokenize the command template into a list of arguments%d/%rsubstitution on each token individually (so paths stay within their token boundary)subprocess.Popen(cmd_parts, shell=False)— arguments are passed directly to the OS without shell interpretationshell=False)Test plan
pytest core/tests/app_test.py— 38 tests pass🤖 Generated with Claude Code