Hiya, this is potentially dangerous:
If $a was previously used as an array (or hash), then: declare a=$external_input (or: declare -r a=$external_input for instance (or -l...)... but not: readonly a=$external_input (or export) ) becomes a code injection vulnerability: $ b='($(uname>&2))' bash -c 'a=(); declare -r a=$b' Linux That could be an issue in scripts that are meant to be sourced or functions that call other functions before using "declare". That's aggravated by the fact that the issue doesn't show up unless $external_input starts with (. If not changed, that behaviour may be worth documented. ksh behaviour that only accepts "(" when litteral and unquoted (or zsh that doesn't accept it at all) is a bit saner IMO. In ksh: $ typeset -a a="(2)"; echo "$a" (2) There also seems to be a minor bug there in bash: $ b='($(uname))' bash -c 'declare -a a; declare a="$b"; printf "<%s>\n" "$a" "${a[0]}"' <> <Linux> $ b='($(uname))' bash -c 'a=(); declare a=$b; printf "<%s>\n" "$a" "${a[0]}"' <Linux> <Linux> (I'd expect the same result for both). Note that's also the case when the variable was previously defined as integer (and that's also the case for mksh) but those cases would usually be detected I think: $ b='z[0$(uname>&2)]' bash -c 'declare -i a; declare a=$b; echo "$a"' Linux 0 It may be worth recommending people do a "unset var" before doing a "declare [-<option>] var" unless they do intend to retain the previous value and/or type especially if they don't have control on what was executed beforehand in the same context (though in that case one may argue that they should use their own context and make sure they don't call other functions that modify variables in their parent context or be aware of what variables the functions they call may modify (recursively)). -- Stephane