Product SiteDocumentation Site

5.2.2. Double expansion

Double expansion occurs when, during the expansion of a shell variable, not just the variable is expanded, replacing it by its value, but the value of the variable is itself is expanded as well. This can trigger arbitrary code execution, unless the value of the variable is verified against a restrictive pattern.
The evaluation process is in fact recursive, so a self-referential expression can cause an out-of-memory condition and a shell crash.
Double expansion may seem like as a defect, but it is implemented by many shells, and has to be considered an integral part of the shell programming language. However, it does make writing robust shell scripts difficult.
Double expansion can be requested explicitly with the eval built-in command, or by invoking a subshell with “bash -c”. These constructs should not be used.
The following sections give examples of places where implicit double expansion occurs.

5.2.2.1. Arithmetic evaluation

Arithmetic evaluation is a process by which the shell computes the integer value of an expression specified as a string. It is highly problematic for two reasons: It triggers double expansion (see Section 5.2.2, “Double expansion”), and the language of arithmetic expressions is not self-contained. Some constructs in arithmetic expressions (notably array subscripts) provide a trapdoor from the restricted language of arithmetic expressions to the full shell language, thus paving the way towards arbitrary code execution. Due to double expansion, input which is (indirectly) referenced from an arithmetic expression can trigger execution of arbitrary code, which is potentially harmful.
Arithmetic evaluation is triggered by the follow constructs:
  • The expression in “$((expression))” is evaluated. This construct is called arithmetic expansion.
  • $[expression]” is a deprecated syntax with the same effect.
  • The arguments to the let shell built-in are evaluated.
  • ((expression))” is an alternative syntax for “let expression”.
  • Conditional expressions surrounded by “[[]]” can trigger arithmetic evaluation if certain operators such as -eq are used. (The test built-in does not perform arithmetic evaluation, even with integer operators such as -eq.)
    The conditional expression “[[ $variable =~ regexp ]]” can be used for input validation, assuming that regexp is a constant regular expression. See Section 5.5, “Performing input validation”.
  • Certain parameter expansions, for example “${variable[expression]}” (array indexing) or “${variable:expression}” (string slicing), trigger arithmetic evaluation of expression.
  • Assignment to array elements using “array_variable[subscript]=expression” triggers evaluation of subscript, but not expression.
  • The expressions in the arithmetic for command, “for ((expression1; expression2; expression3)); do commands; done” are evaluated. This does not apply to the regular for command, “for variable in list; do commands; done”.

Important

Depending on the bash version, the above list may be incomplete.
If faced with a situation where using such shell features appears necessary, see Section 5.1, “Consider alternatives”.
If it is impossible to avoid shell arithmetic on untrusted inputs, refer to Section 5.5, “Performing input validation”.