On 11/2/19 12:27 PM, Patrick Blesi wrote: > Upon further inspection, what Andreas pointed out is actually what I need. > Just to close the loop on everything... > > It looks like Ruby does support execution with and without a shell: > https://apidock.com/ruby/Kernel/system. > > The reasoning for using two programming languages is that sometimes it is > easier to accomplish things in Ruby and sometimes it is easier to > accomplish things in a shell. Providing the user the option to implement > something via shell or via Ruby allows for maximum flexibility and utility. What features of a shell are you using here? The only shell code which you are running is:
tmux send-keys -t %1 q C-u "$command" C-m This uses no shell syntax -- no if/while/for loops, word splitting, no pipes, no shell builtin utilities, no process substitution, no arithmetic expansion, and no tilde expansion. The only thing it uses is variable expansion, but that is because you're using lots of additional shell goop to insert a complex command into a shell variable in order to do quotation magic for $command, instead of passing it via argv. I am certainly not going to claim that it's wrong for ruby to include a system() analogue. :/ I'm not even going to claim that it's wrong to seek ways to handle single quotes in ruby's system() analogue, even though I think it probably makes a lot more sense to use a shellescape library for that. (General rule of thumb for shellescaping strings: replace every instance of a single quote with the four-character sequence: '\'' and then single-quote the whole thing. Single quotes suppress interpretation of everything other than single quotes, and for the single quotes themselves, you temporarily leave the quoting context and use a backslash-escaped single quote.) What I am going to claim is that you're incorrect for thinking you must use a shell in the first place. Save your escaping tricks for cases where you actually require interpreting your command in a shell, and for this case here, use an exec. It's not just about security, which you've already stated is not about being secured. It's not just about avoiding erroneous handling, since your tremendous hack "probably" works, and shellescape routines work somewhat more reliably, so avoiding erroneous handling can be done. It's also about efficiency: you're randomly introducing a shell in order to run your subprocess, even though you don't need a shell at all, and as a result your program runs slower, because it proxies subprocesses through additional helper processes (in this case the shell). Why are you going through convoluted, non-intuitive steps in order to take a ruby variable and pass it as one of a series of arguments to the "tmux" subprocess by first converting it to a shell variable using dark sorcery and doing the passing of arguments in shell code? Moreover since not only do you not want to interpret the user-provided input as shell metacharacters, but you don't even want to use shell metacharacters in your hardcoded component either. -- Eli Schwartz Arch Linux Bug Wrangler and Trusted User
signature.asc
Description: OpenPGP digital signature