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. Regarding, posix compliance, I was specifically asking about whether the following code could be expected to be supported by any POSIX-compliant shell: command=$(cat <<'MAGIC_WORD' #{command} MAGIC_WORD ) tmux send-keys -t %1 q C-u "$command" C-m Not sure if this is the canonical POSIX shell reference: https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_07_04, but it appears that the quoted here-doc and command substitution are shell features defined by the POSIX standard. Thank you very much for your help. -- Patrick On Fri, Nov 1, 2019 at 3:44 PM Eli Schwartz <eschwa...@archlinux.org> wrote: > On 11/1/19 3:57 PM, Patrick Blesi wrote: > > The actual use case is taking a command from a Ruby script: > > > > > https://github.com/braintree/runbook/blob/4a0f0770a8a2a7be135cf13ee435d981b5975a06/lib/runbook/helpers/tmux_helper.rb#L23 > > > > `tmux send-keys -t #{target} #{_pager_escape_sequence} '#{command}' C-m` > > > > The user specifies the command they want to run as a Ruby string and it > > gets interpolated into the above string and then executed (The backticks > in > > Ruby invoke the command in a subprocess and return the output as a > string, > > #{} is string interpolation). As you can see, if the user-specified > command > > has a single quote, it will break this command unless escaped. > > I don't know about ruby. > > I know that in, say, python, the subprocess module can take an array > with a command executable and its arguments, and execute it using the > exec() family of functions. > > You can optionally request that the subprocess module do its execution > via a shell, just like system() does, but it's generally not exactly > recommended. > > Have you considered rewriting your ruby program to not use vulnerable > methods of executing subprocesses? Given that ruby is, presumably, a > powerful programming language, I don't understand why you would want to > write a program that now uses *two* programming languages: > > - ruby > - /bin/sh > > when you could do all your work in ruby. > > If you absolutely require using shell syntax in your subprocess for > inexplicable reasons, you can use the shell syntax embedded within this > pseudocode, which would be executed using the exec() family of functions: > > {'sh', '-c', 'do_things "$1"', '_', 'argv_containing_user_input'} > > given sh is being passed an argument without introducing a shell, and > that argument is assigned to the shell variable $1, that argument can be > defined and passed to exec() containing anything which ruby wants to put > there. > > Safely. > > > I think doing something like this should serve my needs: > > > > ` > > command=$(cat <<'MAGIC_WORD' > > #{command} > > MAGIC_WORD > > ) > > tmux send-keys -t #{target} #{_pager_escape_sequence} "$command" C-m > > ` > > So that no single quote escaping is required. The non-valid input for the > > command would be MAGIC_WORD. Do you know if this command is POSIX > > compliant/supported by a large number of shells? Is is supported by the > > bourne shell? > > Is what command POSIX compliant? > > - The one you're proposing be added, right now, to bash and bash alone? > - tmux? > - cat with quoted delimiter tokens? > > -- > Eli Schwartz > Arch Linux Bug Wrangler and Trusted User > >