Skip to content
shellhacks.dev
Security

Avoid eval on input

Never pass input to eval. Run a command held in an array as "${cmd[@]}", or escape a value with printf %q when eval cannot be avoided.

1 min read
Summarize in AI

A script builds a command from a value the user typed and runs it with eval, which runs whatever else the value contains.

Shell
user_input='x; echo INJECTED'
eval "echo $user_input"
echo ---
eval "echo $(printf '%q' "$user_input")"
echo ---
cmd=(echo "$user_input")
"${cmd[@]}"
Text
x
INJECTED
---
x; echo INJECTED
---
x; echo INJECTED

eval joins its arguments into a string and parses it again as shell code, so the semicolon in the input ends the first command and starts a second one, which printed INJECTED. printf %q quotes the value so that it parses back as one word. An array avoids the second parse altogether, since each element stays one argument, and "${cmd[@]}" runs it. The Bash FAQ covers building commands this way.

%q output is Bash specific and its quoting style can differ between versions, so do not use it for data that another shell reads. Arrays need Bash or another shell with arrays. An indirect variable, ${!name}, or declare -n replaces most uses of eval for variable names, and a name taken from input should be checked against a pattern first.

Share

More snippets

Security

Avoid predictable temp names

Never build a temp file name from $$ or a fixed string. An attacker who guesses it can plant a symlink, and mktemp picks an unused random name with mode 600.

1 min read
Security

Quote variables passed to commands

Quote variables you pass to commands. An unquoted expansion splits on spaces and expands globs, and a value that starts with a dash becomes an option.

1 min read
Security

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.

1 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.