bash.lang.correctness.unquoted-expansion.unquoted-variable-expansion-in-command

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Variable expansions must be double-quoted so as to prevent being split into multiple pieces according to whitespace or whichever separator is specified by the IFS variable. If you really wish to split the variable's contents, you may use a variable that starts with an underscore e.g. $_X instead of $X, and semgrep will ignore it. If what you need is an array, consider using a proper bash array.

Run Locally

Run in CI

Defintion

rules:
  - id: unquoted-variable-expansion-in-command
    languages:
      - bash
    severity: INFO
    message: Variable expansions must be double-quoted so as to prevent being split
      into multiple pieces according to whitespace or whichever separator is
      specified by the IFS variable. If you really wish to split the variable's
      contents, you may use a variable that starts with an underscore e.g. $_X
      instead of $X, and semgrep will ignore it. If what you need is an array,
      consider using a proper bash array.
    metadata:
      category: correctness
      technology:
        - bash
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    patterns:
      - pattern-either:
          - pattern: |
              ... ${$VAR} ...
          - pattern: |
              ... ...${$VAR}... ...
      - metavariable-regex:
          metavariable: $VAR
          regex: "[*@0-9]|[A-Za-z].*"

Examples

unquoted-expansion.bash

##################### Variable expansion #############################

# ruleid: unquoted-variable-expansion-in-command
exec $foo

# ruleid: unquoted-variable-expansion-in-command
exec $FOO

# ruleid: unquoted-variable-expansion-in-command
exec ${foo}

# ruleid: unquoted-variable-expansion-in-command
exec $1

# ruleid: unquoted-variable-expansion-in-command
exec ${foo%.bar}

# ruleid: unquoted-variable-expansion-in-command
exec $foo.bar

# ruleid: unquoted-variable-expansion-in-command
exec ${foo}.bar

# ok: unquoted-variable-expansion-in-command
exec "$foo"

# ok: unquoted-variable-expansion-in-command
exec "$FOO"

# ok: unquoted-variable-expansion-in-command
exec "${foo}"

# ok: unquoted-variable-expansion-in-command
exec "$1"

# ok: unquoted-variable-expansion-in-command
exec "${foo%.bar}"

# ok: unquoted-variable-expansion-in-command
exec "${foo}.bar"

# ok: unquoted-variable-expansion-in-command
exec "${foo}".bar

# ok: unquoted-variable-expansion-in-command
exec "$foo".bar

# ok: unquoted-variable-expansion-in-command
x=$foo

# ok: unquoted-variable-expansion-in-command
PATH=$foo:$PATH bar

# Expands without splitting (if IFS wasn't tempered with)
# ok: unquoted-variable-expansion-in-command
echo $$

# Special exception for semgrep users: $_foo is tolerated.
# ok: unquoted-variable-expansion-in-command
echo $_foo

##################### Command substitution #############################

# ruleid: unquoted-command-substitution-in-command
exec $(foo)

# ruleid: unquoted-command-substitution-in-command
exec `foo`

# ruleid: unquoted-command-substitution-in-command
exec $(foo)bar

# ruleid: unquoted-command-substitution-in-command
exec bar$(foo)

# ruleid: unquoted-command-substitution-in-command
exec bar$(foo)bar

# ruleid: unquoted-command-substitution-in-command
exec bar`foo`bar

# ok: unquoted-command-substitution-in-command
exec "$(foo)"

# ok: unquoted-command-substitution-in-command
exec "`foo`"

# ok: unquoted-command-substitution-in-command
exec "bar$(foo)bar"

# ok: unquoted-command-substitution-in-command
x=$(foo)