I don't think that setting IFS this way is a good idea. Of your variables do happen to contain tabs and newlines, you still get unwanted word expansion. Much better is to just use double quoted expansion primitives that always expand one element to each word: "${foo[@]}"
That's the common answer, and while I practice that myself, I have to disagree with it as guidance. Maybe you and I are fastidious enough to always remember to quote all our variables, but many are not - I know I was writing shell scripts for a couple of years before I realized its importance, and it's very common that even experienced engineers don't know or care to do it. If someone writing or editing the code forgets to quote the variable that allows subtle bugs to sneak in.
It's unfortunate the semantics of bash don't have variable references behave like they are quoted by default. I really wish it did.
If you can remember to use $@ rather than $*, you should be able to remember to use "$@". The only reason $@ exists is that it behaves differently when enclosed in double quotes.
While setting IFS=$"\t\n" may make problems less likely when strings contain spaces, it's still not correct. File names (and other strings) can contain tabs and newlines, too. That's relatively rarer, but the quoting approach always works.
#!/bin/bash
items=(
'a'
'b c'
"d\te"
"f\ng"
)
echo "Unquoted:"
for item in ${items[@]}; do
echo -e ". $item"
done
echo "Quoted:"
for item in "${items[@]}"; do
echo -e ". $item"
done
set -euo pipefail
IFS=$'\n\t'
echo "Unquoted strict mode:"
for item in ${items[@]}; do
echo -e ". $item"
done
... I get this output:
Unquoted:
. a
. b
. c
. d e
. f
g
Quoted:
. a
. b c
. d e
. f
g
Unquoted strict mode:
. a
. b c
. d e
. f
g
Note the output for "Quoted" and "Unquoted strict mode" are identical.
(GNU bash, version 4.2.37(1)-release (x86_64-pc-linux-gnu))
Can you give an example of an exploit in bash? The link you give is excellent information, but doesn't have any shell script examples.
My first thought: It seems like only $@, $* and variables read from the environment could be possible attack vectors. But since shell scripts can't be setuid, it's hard for me to immediately imagine how unquoting could enable a new exploit.
EDIT: the most dangerous example I can think of right now is a script like this, where a webapp invokes the script and passes a GET param as an argument: