Gunstick has asked for the wisdom of the Perl Monks concerning the following question:

Hi

a similar topic already came up which was about how to quote shell parameters so they are safe to pass to the shell.
I have another problem, I get as input a string containing the shell command to execute with it's parameters. Now I want to re-quote that so it's not going to execute something unwanted.
e.g. this

ls -al "file 1" "file'2" ; cat /etc/passwd
is transformed into
ls '-al' 'file 1' 'file'\''2' ';' 'cat' '/etc/passwd'
and ls will complain about non found files ";" and "cat".
Here is the current code I have come up with.
#!/usr/bin/perl # used http://www.cs.hmc.edu/courses/2003/spring/cs60/fsm.pdf # to transform state machine into regexp $cmd=<>; $arg=""; chomp $cmd; $cmd.=" "; # regexp # ( |([^'"\\ ]+)|(\\.)|("(([^"\\])|(\\.))*")|('[^']*')) # only global matching # ( |(?:[^'"\\ ]+)|(?:\\.)|(?:"(?:(?:[^"\\])|(?:\\.))*")|(?:'[^']*')) # we need to do second subst to remove " and ' pairs and unescape \ so + need some flags # ( |(?:[^'"\\ ]+)|(\\.)|("(?:(?:[^"\\])|(\\.))*")|('[^']*')) while($cmd=~s/^( |(?:[^'"\\ ]+)|(\\.)|("(?:(?:[^"\\])|(\\.))*")|('[^'] +*'))(.*)$/$6/) { $c=$1; # the flags... $esc=$2; $dquote=$3; $dquoteEsc=$4; $squote=$5; print "c=$c arg=$arg cmd=$cmd esc=$esc dquote=$dquote dquoteEsc=$dqu +oteEsc squote=$squote\n"; if($c eq " ") { $arg=~s/'/'\\''/g; # shell escape the ' $res .= "'$arg' "; $arg=""; next; } if(($esc ne "")|($dquoteEsc ne "")) { $c=~s/\\//g } if($dquote ne "") { $c =~ s/^"(.*)"$/$1/} if($squote ne "") { $c =~ s/^'(.*)'$/$1/} $arg .= $c; } print "$res\n";

Replies are listed 'Best First'.
Re: safe quoting for shell parameters
by Aristotle (Chancellor) on Jan 01, 2004 at 22:58 UTC
      yes, that's a part of a solution, but it's not doing the main job: parsing a string of parameters and quoting them. It just quotes one parameter.

      See:
      ls a b c
      is transformed into
      ls 'a b c'
      which results in ls: a b c: No such file or directory


      Useful? No :-) And splitting by spaces won't help, e.g.
      ls "a' b" c gives
      ls '"a'\' 'b"' 'c' instead of
      ls 'a'\'' b' 'c'

Re: safe quoting for shell parameters
by sgifford (Prior) on Jan 01, 2004 at 21:56 UTC

    If you're reading the command to execute from the user, they can already run whatever command they want. What's the point of trying to stop them from being tricky with shell escapes when they can just run their program directly, by sending it to you in $cmd?

    A design like this only makes sense if you pretty much completely trust the person sending input to the script.

      Where do I say that reading the command from the user imply they can run any command??? This is not true.
      In this case the user cannot run any command, it is a part of an ssh wrapper script and the variable to parse escape-free is $SSH_ORIGINAL_COMMAND
Re: safe quoting for shell parameters
by Anonymous Monk on Jan 02, 2004 at 21:30 UTC