-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CTRL-R can cause accidental code injection through fzf --query
flag in shell scripts
#3185
Comments
Thanks for the heads up. I don't see this as a problem. If this is a problem, then we're saying that every command-line program that takes an arbitrary string as an argument has the problem. i.e. grep, sed, awk, to name a few. When a script or a program is invoking a shell command, it is its responsibility to properly escape the arguments. You can find libraries for that purpose in many programming languages. They're usually called |
@junegunn No, this is very different from grep/etc because CTRL-R automatically passes the raw input line to Depending on what the user has typed into the shell input line so far, pressing CTRL-R can unwittingly trigger code injection and mistakenly execute part of the input line. I meant that CTRL-R's usage of The fix for CMD involves stripping |
--query
flag in shell scripts has potential code injection case--query
flag in shell scripts
The code is perfectly fine and safe because the varible reference is quoted. bash and zsh don't have the problem you describe. Maybe quoting is not good enough in cmd.exe, but this repository doesn't provide any cmd.exe script. |
I see. Bash explicitly avoids parsing what's inside the expanded I don't expect fzf to support cmd.exe. But for context, cmd.exe expands variables and then parses the resulting command line. It isn't my intent to debate pros/cons of different shell designs; I only want to help ensure safety in each shell. The external integration scripts for fzf and cmd.exe handle this safely in a cmd.exe-specific way. Thanks! |
Follow-up for those who are curious about the details how this worksI couldn't find any documentation explaining how quoting a shell variable works. It seemed strangely complicated and problematic for bash to be able to avoid parsing the expanded variable, and my curiosity was piqued. And indeed, that's not how it works. So I tracked it down. Short versionBash automatically applies escaping when a variable expansion happens within double quotes such as Cmd does not automatically apply escaping; it must be done manually. I wasn't able to find anything that actually stated that bash applies escaping when variable expansion happens within double quotes; I had to determine it empirically. Presumably I just didn't know the right search terms to find it. Long versionI'm using WSL (Windows subsystem for Linux), so each separate terminal is a separate instance of Linux. They're unaware of each other, so I couldn't use So I took an "easy way out" and copied the How variable quoting works in bashWhen bash expands When parsing a command line, within a double quoted run The actual command line passed to the spawned process contains both the outer quotes and the escaped inner quotes, for example How command lines are handled on WindowsThis is not meant as a critique of how Windows works, nor why it works that way, it is just an explanation of how it is. There are historical reasons why, and in the context of the time they were made, most of them actually make sense as pragmatic trade-offs. (Tracking down all the historical reasons is left as as exercise for the reader.) Synopsis:
Knowing how command line parsing working on Windows, we would expect the following:
And generally speaking, it does, if an executable program (a .exe file) is spawned. But if it spawns a cmd shell script, then cmd will parse the command line differently, and things can get tricky. That's just part of cmd shell scripting, but the trouble is the caller has to format the command differently depending on whether it will be parsed by a cmd shell script, or by an executable program. ConclusionBash automatically applies escaping when a variable expansion happens within double quotes such as Cmd does not automatically apply escaping; it must be done manually. On Windows, it should be possible to explicitly invoke |
man fzf
)Info
Problem / Steps to reproduce
The way that the
--query
flag is used has a code injection issue.In different shells, different kinds of input characters can cause part of the
--query
string to get misinterpreted by the shell as another command.This was first noticed with cmd.exe + clink and clink-fzf, which contains a Lua script for integrating fzf with Clink.
If the
--query
argument string is not quoted, then text like& echo hello
can result in theecho hello
part of the query text getting interpreted as a separate shell command, instead of as a query string.If the
--query
argument string is quoted, then text likeexe" & echo hello
can result in theecho hello
part getting interpreted as a separate shell command, instead of as a query string.If the
echo hello
in the example is replaced by other more dangerous text, then very unfortunate accidental side effect could occur, just from trying to search in the command history. For example, in cmd.exerd /s
would recursively removes all directories.This is fixed for cmd.exe + clink by chrisant996/clink-fzf@5415363.
Other shells could likely use a similar approach of stripping certain problematic characters (especially quotes) and surrounding the reduced query string in quotes. The specific set of problematic characters is different for different shells.
The text was updated successfully, but these errors were encountered: