VNX-BASH-004 – Unquoted Variable Used in Command or Test
Overview
This rule flags lines in Bash or shell scripts (.sh, .bash) where a variable reference $VAR appears inside a single-bracket [ ] test expression without surrounding double-quotes. The rule specifically targets the older POSIX [ ] test construct rather than the Bash-extended [[ ]], which handles word splitting internally. Lines that are commented out or that use [[ ]] are excluded.
When a variable is unquoted inside [ ], the shell performs word splitting on its value before passing it to the test command. A variable containing a space becomes two separate tokens, causing the test to receive the wrong number of arguments and behave unexpectedly or throw a syntax error. A value containing glob characters such as * or ? triggers filename expansion, potentially matching unintended files from the working directory.
The security impact is more direct when the variable value is attacker-controlled. An adversary who can set a variable to a string with carefully placed spaces or shell metacharacters can manipulate conditional logic, bypass checks, or inject additional arguments into the test command.
Severity: Medium | CWE: CWE-78 – Improper Neutralisation of Special Elements Used in an OS Command
Why This Matters
Argument injection through word splitting is a subtle but serious vulnerability class in shell scripts. Unlike obvious command injections via eval, unquoted variable expansion attacks exploit the shell’s own parsing rules. A file named foo bar in a directory, or an environment variable containing a space set by a malicious actor earlier in a pipeline, can silently change the logic of a security check.
Consider an access-control script that checks a username from an environment variable: if the username is alice admin, the unquoted test [ $USERNAME = "alice" ] becomes [ alice admin = "alice" ], which is a syntax error — the check silently fails open or causes an unhandled exit depending on how errors are handled. Real-world CI/CD systems have been exploited through injected branch names or commit message content that ended up in shell variable comparisons without quoting.
ATT&CK technique T1059.004 covers Unix shell abuse, and CAPEC-88 describes argument injection — both are relevant here because exploiting this pattern can allow an attacker to alter the behaviour of security-relevant conditional checks in scripts.
What Gets Flagged
# FLAGGED: $username unquoted inside [ ] test
if [ $username = "admin" ]; then
grant_access
fi
# FLAGGED: $file_path unquoted, glob expansion risk
if [ -f $file_path ]; then
process_file
fi
# FLAGGED: unquoted $status in equality check
[ $status == "ok" ] && deploy
Remediation
- Always double-quote variable references inside
[ ]tests:[ "$var" = "value" ]. - Prefer
[[ ]]in Bash scripts — it does not perform word splitting or glob expansion on variable expansions, making it safer by default. - Enable
set -uso that any reference to an unset variable is caught immediately rather than silently expanding to empty. - Use ShellCheck as part of your CI pipeline to catch unquoted variable usage automatically.
# SAFE: double-quoted variable in [ ] test
if [ "$username" = "admin" ]; then
grant_access
fi
# SAFE: [[ ]] handles word splitting internally (Bash only)
if [[ $username == "admin" ]]; then
grant_access
fi
# SAFE: quoted and using [[ ]] for file test
if [[ -f "$file_path" ]]; then
process_file
fi