Preventing Command and Argument Injection
Quote, validate, and array-pass untrusted input to eliminate word-splitting and eval-based injection.
Why Injection Attacks Happen in Bash
Bash is a powerful glue language — it passes text directly to the kernel, other programs, and sub-shells. That power becomes a liability the moment untrusted input reaches a command without validation or quoting.
Two root causes drive nearly every Bash injection:
- Word splitting: Unquoted variables are split on whitespace (
IFS), turning one logical value into many shell tokens. - Glob expansion: Characters like
*,?, and[are expanded by the shell before the command even runs.
An attacker who controls a filename, username, URL parameter, or environment variable can exploit both to run arbitrary commands, read files, or escalate privileges.
This lesson shows exactly how these vulnerabilities appear and — more importantly — how to eliminate them with correct quoting, input validation, and array-based argument passing.
Word Splitting: The Silent Threat
When Bash sees an unquoted variable, it splits its value on any character listed in $IFS (default: space, tab, newline). What looks like one argument becomes many.
Run the script below and observe how a filename with a space becomes two separate arguments to rm.
#!/usr/bin/env bash
# Dangerous: unquoted variable
FILE='important file.txt'
# Create the file so the demo is self-contained
touch "$FILE"
echo "Files before:"
ls
# BUG: rm sees TWO arguments: 'important' and 'file.txt'
# If 'important' does not exist, rm prints an error but continues.
rm $FILE # <-- unquoted, word-split happens here
echo "Files after (unquoted rm):"
lsAll lessons in this course
- Preventing Command and Argument Injection
- Secure Secret Handling and Environment Hygiene
- Least-Privilege Execution and sudo Discipline
- Static Analysis and Auditing with ShellCheck