[cs615asa] hw5 Question

Jan Schaumann jschauma at stevens.edu
Fri Apr 5 12:36:32 EDT 2019

Justin Barish <jbarish at stevens.edu> wrote:
> However, from trying this, I cannot get this to work, in that sh will not
> expand the tilde, so I get:

Ah, yes, you discovered the fun world of tilde expansion!

See the sh(1) manual page and search for "Tilde Expansion".

The easiest solution might be to simply not allow the variable to be set
in this way, but that would be very confusing to the user.

Users are used to be able to run this command:

ssh -i ~/.ssh/ec2-key hostname

so they would expect that setting EC2_BACKUP_FLAGS_SSH="-i
~/.ssh/ec2-key" should work.  Let's see how the expansion works in shell
scripts.  Fetch this script and run it:

The output should look somewhat like this:

A quoted ~ is not going to get expanded:
Setting 'SSH_KEY1="~/.ssh/ec2-key"' yields:

An unquoted ~ is going to get expanded:
Setting 'SSH_KEY1=~/.ssh/ec2-key' yields:

Ok, so how about an unquoted ~ arg in a multi-arg string?
Setting 'EC2_BACKUP_FLAGS_SSH=-i ~/.ssh/ec2-key' will yield an error.
So we _have_ to quote it:
I.e., we set 'EC2_BACKUP_FLAGS_SSH="-i ~/.ssh/ec2-key"':
EC2_BACKUP_FLAGS_SSH=-i ~/.ssh/ec2-key

But how do we get '~' to expand now?

One way might to explicitly eval the variable:
This then yields:
EXPANDED_VARIABLE=-i /Users/jans/.ssh/ec2-key

Ok, so that works, but that means we're evaluating user input unchecked.
Suppose the user sets EC2_BACKUP_FLAGS_SSH="whatever; rm -fr /"...

Let's illustrate with a less harmful version:
EC2_BACKUP_FLAGS_SSH="whatever; touch /tmp/newfile"

This then yields:

And now...
ls -l /tmp/newfile
-rw-------  1 jans  staff  0 Apr  5 12:30 /tmp/newfile

Ok, let's remove that file again.
rm -f /tmp/newfile

This is a classical example of command-injection via environment
For this reason, you must not trust the environment!

Hmm, so how do we expand ~ then?

We can manually translate it, since we know have the user's
HOME directory in the environment:
echo ${HOME}

So let's try that:
EC2_BACKUP_FLAGS_SSH="-i ~/.ssh/ec2-key"
EC2_BACKUP_FLAGS_SSH="$( echo ${EC2_BACKUP_FLAGS_SSH}" | sed -e "s|~|${HOME}|g")"
Now let's see if this expanded correctly:
-i /Users/jans/.ssh/ec2-key


So I'd probably suggest this approach.  Note that (a) you need to quote
the args to sed(1) to ensure expansion of the HOME and (b) you can't use
'/' as the separator in the sed substitution, as '/' are the path
separators in the expanded HOME variable.

I hope this didn't make things too confusing, but it nothing else, it
serves as a good example of how something as seemingly trivial as tilde
expansion may require a somewhat deeper understanding of how the shell
works to get it right.


More information about the cs615asa mailing list