1

I am running a command in a bash script that uses the content of a file as an argument. Here a simplified example:

USER=$(<$fileA)
PASSWORD=$(<$fileB)
wget -u $USER -p $PASSWORD

However, the content of the file can be set to any value by the user. I assume I need to escape this, but I don't know how to do that, especially in a way that $PASSWORD will NOT be altered. Otherwise the password will obviously not work.

Thanks

2
  • You shouldn't use the variable name USER -- it's prepopulated by the shell with the current user's username, and changing it may confuse anything that expects it to have that value. There are a bunch of all-caps variables with special meanings, so it's best to use lower- or mixed-case names for your variables, to avoid possible conflicts. Commented Sep 2, 2018 at 2:17
  • 1
    If you execute that line, then the username and password are exposed to anyone who happens to be logged on to your machine (through /proc/<pid>/cmdline, for example, or with even less work through the ps` command). With curl, you can create a less insecure command-line: echo user|cat "$fileA" "$fileB"|paste -sd:|curl -K- http://www.example.com. Commented Sep 2, 2018 at 3:09

1 Answer 1

2

You probably simply need to add quotes around the variables.

wget -u "$USER" -p "$PASSWORD"

If you happen to capture a newline at the end of the variable, you may want to strip it with:

wget -u "${USER%$'\n'}" -p "${PASSWORD%$'\n'}"

The ${var} syntax is equivalent to $var but curly braces allows to manipulate variables with bash. By adding %$'\n' before the ending curly brace, the % means to remove the text $'\n', which means removing the trailing newline, if any.

In the worst case scenario, you may get newline and carriage returns (probably if the files were generated by a text editor in Windows), but you can also deal with it:

wget -u "${USER%%[$'\n'$'\r']*}" -p "${PASSWORD%%[$'\n'$'\r']*}"

This time around, the searched text is [$'\n'$'\r']* which is means "the first newline (\n) or carriage return (\r) and everything after" and the %% operator means "remove the longest sequence at the end".

Sign up to request clarification or add additional context in comments.

6 Comments

The last one (for DOS/Windows line endings) doesn't work -- the pattern [$'\n'$'\r'] only matches a single character (either carriage return or newline), not a sequence of them. And it's actually a glob pattern not a regex, so you can't just add * to the end to match multiple instances. You could do it with extglob...
And I don't think "${USER%$'\n'}" will ever do anything since command substitution $(...) strips trailing newlines.
@GordonDavisson Thank you for the correction. I edited the answer.
@PesaThe You’re right but ultimately I don’t know if the OP will use $() to capture the input, in which case the answer may be of interest. Plus it makes the transition easier to the following parameter substitution.
@vdavid Also care with [$'\n'$'\r']*. It doesn't remove trailing newlines or carriage returns. It is not a regex and in fact it removes anything up to the first \n or \r present in the string. Try it for: var=$'abc\ndef\n123\n'. You could use extglob, as Gordon suggested: ${var%%+([$'\n\r'])}.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.