Validate input with a whitelist
Validate input against a list of allowed values with a case statement. A grep check with ^ and $ can be fooled by a value that holds a newline.
A script takes an action name from outside and must refuse everything that is not on a short list.
validate() { case $1 in start|stop|status) return 0 ;; *) return 1 ;; esac; }
for a in start 'start; reboot' ''; do
validate "$a" && echo "ok: [$a]" || echo "rejected: [$a]"
done
echo ---
input=$'start\nrm -rf /'
printf '%s' "$input" | grep -qE '^(start|stop)$' && echo "grep: accepted" || echo "grep: rejected"
validate "$input" && echo "case: accepted" || echo "case: rejected"ok: [start]
rejected: [start; reboot]
rejected: []
---
grep: accepted
case: rejectedA case pattern must match the whole string, so only the three exact words pass, and anything else, including the empty value, falls through to the default. grep works one line at a time and its anchors match at each line, so a value that holds a newline passes if any single line looks right. Here the first line is start, and the dangerous second line is never examined. The matching rules are in the Bash manual.
The list approach fits a short set of fixed words. For a format, such as a number or a host name, [[ $x =~ ^[0-9]+$ ]] in Bash matches the whole string, though a trailing newline can still slip through $, so check with a character class that excludes newlines first. Validate where the value is used, not only where it arrives.