intro

eval is considered bad in many languages, including bash. In this case study, we’ll talk about an alternative to eval, but still quite effective.

case study

In bash scripting, we can use [] as an equivalent to test. In some implementations, you may see people using [[]] instead, and it’s considered a much more reliable version of test. Inside the test, the expression will be evaluated and very often we have [[ expr -eq "123" ]].

In the above expression, the part expr and "123" will be interpreted in the arithmetic context hence evaluated. Let’s see an example script:

test='1+3'
if [[ "$test" -eq "5" ]]; then
    echo "1"
else
    echo $test
fi

if [[ "$test" -eq "4" ]]; then
    echo "2"
else
    echo $test
fi

The output from the script will be like this

# bash test.sh
1+3
2

This means, the variable test='1+3' has been evaluated arithmetically. And if we were to exploit this characteristic, we could do things like the following

$((expr))
((expr))
${var:expr:expr}
${var[expr]}
var[expr]

Let’s try modify the script and see the effect

test='a[$(date >&2)]+1'
if [[ "$test" -eq "1" ]]; then
    echo "1"
else
    echo $test
fi

This will output the following, which means, the expression $(date >&2) has been executed.

# bash test.sh
Thu Feb 23 08:03:55 PM EST 2023
1

how to prevent this?

Basically nothing really effective. One could attempt to do better input validation on user supplied inputs. But in the end, bash is not a programming language.