🛠 ShellCheck as small helper
Salute,
Today I want to look at the ShellCheck tool with you.
This is a static analyzer of shell scripts such as sh, bash, dash, ksh, which looks for unsafe constructs and non-portable code.
This is a CLI utility (GPLv3) that parses scripts, builds ASTs and verifies rules, displays typical syntax errors in runtime, as well as semantic ones.
Another useful feature is corner‑case.
Teams
# Fetch shell type
shellcheck -s bash script.sh
shellcheck --shell=sh script.sh
# Checking multiple files
shellcheck scripts/*.sh
find . -type f -name '*.sh' -print0 | xargs -0 shellcheck
# Ignore
shellcheck -e SC2086,SC1090 script.sh
# Optional checks
shellcheck -o avoid-nullary-conditions script.sh
# Narrowing the check
shellcheck --source-path=./lib:./scripts main.sh
# ENV control
export SHELLCHECK_OPTS='--shell=bash --exclude=SC2016 -o all'
shellcheck script.sh
Conclusion
shellcheck -f tty script.sh
shellcheck -f gcc script.sh # file:line:column:msg
shellcheck -f json script.sh # JSON
shellcheck -f checkstyle script.sh # XML for CI
shellcheck -f sarif script.sh # SARIF
Example of a bug almost like a feature
# Let's now check why it can help and what can be unpleasant.
# loss of state in loops where while is executed in the subshell, and count outside will remain 0.
# ShellCheck will highlight while read as a potential problem, which is important to us
count=0
cat file | while read -r line; do
count=$((count + 1))
done
echo "$count"
CI/CD
name: shellcheck
on: [push, pull_request]
jobs:
lint-shell:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ShellCheck
run: sudo apt-get update && sudo apt-get install -y shellcheck
- name: Run ShellCheck
run: |
git ls-files '*.sh' | xargs shellcheck -s bash -o all -e SC1090
Total:
• This helper helps you use it as a premerger and control developers so that they can avoid problematic patterns that will affect security
• Tula will help you be more confident that when setting up rules, you will partially reduce the input vector of attacks and cover what you usually think “oh well, this won’t happen”
• Globally disable only rules that are obviously inappropriate and use targeted shellcheck disable
• Use a fixed version, so as not to break the build when changes are made, but only output the upgrade reco to a separate log
• Collect a list of git scripts ls-files '*.sh'
• Run with profile -s , -o , -e , -P
• Use non-zero exit code as a crash criterion
Footnote
• Shell is a shell that interprets commands through system calls allowing you to manage the kernel and applications using a shebang
• Corner‑case - a situation when the system behaves differently, for example, a script that works correctly with files, but crashes when there are no files, that is, it has an unprocessed “empty list of files”.
#toolchain #sast #appsec #reco #term
