-1

In Bash scripting, the eval command is often used to execute dynamically generated code. However, I have read that eval can be risky as it can lead to security vulnerabilities and make the code harder to maintain. Therefore, it's generally recommended to avoid using eval whenever possible.

Are there other alternative approaches I can use in bash scripting ?

This is what I am currently using

## start of file
shstate=$(shopt -p extglob)
shopt -s extglob

## sourcing a library here

eval "$shstate"
## end of file
Dilna
  • 405
  • 1
  • 6
  • 1
    `shopt -q extglob && shstate=s || shstate=u` before and `shopt -$shstate extglob` after? – Renaud Pacalet May 11 '23 at 13:17
  • 1
    Does this answer your question? [Why should eval be avoided in Bash, and what should I use instead?](https://stackoverflow.com/questions/17529220/why-should-eval-be-avoided-in-bash-and-what-should-i-use-instead) – pjh May 11 '23 at 13:17
  • If you script is being *executed* (not sourced), there's no reason to restore the setting of `extglob` in the first place, because the shell with that setting exits immediately after you restore the original value. – chepner May 11 '23 at 13:26
  • It is being sourced as part of a library utility for interactive use. – Dilna May 11 '23 at 13:47
  • There's essentially no danger in leaving `extglob` turned on permanently. It's turned on by default in some Bash installations anyway. See [Is it dangerous to always have extglob on?](https://unix.stackexchange.com/q/276911/264812). – pjh May 11 '23 at 19:17

3 Answers3

2

Yet another alternative :

shopt -q extglob || { shopt -s extglob; unset_extglob=1; }

## sourcing a library here

test -v unset_extglob && shopt -u extglob
Philippe
  • 20,025
  • 2
  • 23
  • 32
0

shopt -q extglob does not print anything (because of -q) and its exit status tells if the option is enabled (on success) or disabled (on failure).

You can use this to save the state and restore it later without using eval:

# Save the status of `shopt`
shopt -q extglob
shstate=$?

shopt -s extglob


# Run some code
# ...


# Restore the status of `shopt`
if [ "$shstate" -eq 0 ]; then
  shopt -s extglob
else
  shopt -u extglob
fi
axiac
  • 68,258
  • 9
  • 99
  • 134
  • It does actually give `shopt -s extglob`. – Dilna May 11 '23 at 13:48
  • Please define "it". – axiac May 11 '23 at 14:47
  • A reference to the command `shopt -q extglob` – Dilna May 11 '23 at 15:11
  • In this answer I suggest to use `-q` which means "quiet", not `-p` (which means "print"). Check the [documentation of `shopt`](https://www.gnu.org/software/bash/manual/bash.html#The-Shopt-Builtin) in the Bash manual. – axiac May 11 '23 at 19:24
  • What is the rational behind your approach (-q versus -p) ? Perhaps one can have the option to decide between the two. – Dilna May 12 '23 at 13:53
  • Between which two? You asked how to restore the state of `extglob` without running `eval` because the script sources another script, the included script can overwrite the variable where the command to restore the state of `extglob` has been saved. My answer does not use `eval`. It queries the state of `extglob` and stores the value in a variable. Then it checks the value of the variable and restores the state of `extglob`. If the variable is overwritten the state of `extglob` might be reset incorrectly but there is no risk of injection (because there is no `eval`). – axiac May 12 '23 at 14:50
  • If you do not source another file then there is nothing wrong with your solution using `eval`. – axiac May 12 '23 at 14:51
  • Selection of whether to use `shopt -q extglob` or `shopt -p extglob`. The command `shopt -q extglob` seems more specific because in inquires directly about whether `extglob` is enabled or not. But then `shopt -p extglob` tells you exactly the command to revert. Whereas with `shopt -q extglob` I would have to reconstruct the command myself. – Dilna May 12 '23 at 15:13
  • You want to run a command but you don't want to use `eval`. Here the problem is not `eval`, the problem is that the value of `$shstate` can be replaced by the library sourced before it is `eval`-ed. As long as there is chance to be overwritten, no matter how you execute it, with or without using `eval`, the result is the same: it is a security vulnerability. – axiac May 12 '23 at 20:10
-1

You could read the shopt -p output into an array, and then execute the array as a command:

read -ra current_setting < <(shopt -p extglob)
shopt -s extglob

# do stuff

"${current_setting[@]}"   # restore previous setting
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • This is `eval` under disguise and exposes the same vulnerability as the original solution. Just check what happens if the "stuff" is `current_setting=(ls -l)`. – axiac May 12 '23 at 14:52
  • In what bash version will `shopt -p extglob` output `ls -l`? – glenn jackman May 12 '23 at 15:31
  • 1
    Where your answer says _"# do stuff"_, the question reads _"## sourcing a library here"_. If that library incidentally uses a variable named `current_setting` and stores in it an array like `(rm -rf)`, go figure what `"${current_setting[@]}"` does. – axiac May 12 '23 at 17:25