0Pricing
Linux Command Line & Bash Scripting Mastery · Leçon

Analyse statique et audit avec ShellCheck

Intégrez ShellCheck à une barrière de sécurité et interprétez ses résultats pour renforcer chaque script.

Analyse statique et audit avec ShellCheck est une leçon Linux Command Line & Bash Scripting Mastery gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Linux Command Line & Bash Scripting Mastery, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Linux Command Line & Bash Scripting Mastery comprend 4 leçons au total.

Qu’est-ce que ShellCheck et pourquoi est-ce important

ShellCheck est un outil open source d’analyse statique pour les scripts shell. Il analyse votre code source Bash (ainsi que POSIX sh, dash et ksh) sans l’exécuter et signale les bogues, les constructions dangereuses, les problèmes de portabilité et les problèmes de style — chacun étant associé à un code de règle unique tel que SC2086.

Dans une chaîne de traitement renforcée sur le plan de la sécurité, ShellCheck joue le rôle de barrière obligatoire : aucun script n’est livré tant qu’il n’a pas réussi le contrôle. C’est important, car :

  • De nombreuses vulnérabilités des scripts shell (découpage des mots, injection, expansion non entourée de guillemets) sont invisibles lors des tests du parcours nominal, mais se déclenchent avec des entrées contrôlées par un attaquant.
  • ShellCheck détecte ces catégories de bogues avant l’exécution, sans coût supplémentaire.
  • Il explique pourquoi chaque construction est dangereuse, ce qui sensibilise progressivement votre équipe.

Installez-le sur n’importe quel système :

# Debian / Ubuntu
sudo apt-get install shellcheck

# macOS (Homebrew)
brew install shellcheck

# From source via Cabal (any platform)
cabal update && cabal install ShellCheck

# Verify
shellcheck --version

Exécuter ShellCheck pour la première fois

L’invocation la plus simple est shellcheck <script>. ShellCheck lit la ligne shebang pour déterminer le dialecte du shell, puis écrit ses résultats sur la sortie standard.

Chaque résultat comprend :

  • Fichier et numéro de ligne — emplacement exact
  • Gravité — error, warning, info ou style
  • Code SC — identifiant de règle stable que vous pouvez rechercher ou désactiver
  • Explication en langage clair — indique ce qui est incorrect et souvent comment le corriger

Exécutez le script ci-dessous et observez la sortie que ShellCheck produirait :

#!/usr/bin/env bash
# demo_bad.sh — intentionally flawed for ShellCheck demonstration

FILE=$1

if [ $FILE == '' ]; then
  echo "No file given"
fi

cat $FILE | grep 'error' | wc -l

Interpréter la sortie de ShellCheck et les codes SC

Pour le script de la scène précédente, ShellCheck produirait des résultats tels que :

  • SC2086 (warning) — Entourez de guillemets doubles pour empêcher l’expansion des caractères génériques et le découpage des mots — sur $FILE dans [ $FILE == '' ] et dans cat $FILE.
  • SC2039 / SC3010 (info) — == dans [ ] est une construction propre à Bash ; utilisez = avec POSIX.
  • SC2002 (style) — Cat inutile. Envisagez cmd < file plutôt que cat file | cmd.

Chaque code SC renvoie à une page wiki à l’adresse https://www.shellcheck.net/wiki/SCxxxx, qui fournit la justification et un exemple corrigé.

Voici la version corrigée de ce script :

#!/usr/bin/env bash
# demo_fixed.sh — ShellCheck-clean

FILE="$1"

if [ -z "$FILE" ]; then
  echo "No file given" >&2
  exit 1
fi

grep -c 'error' "$FILE"

Niveaux de gravité et mesures à prendre

ShellCheck classe chaque résultat selon sa gravité. Dans une barrière de sécurité, vous devriez les traiter comme suit :

  • error — Bog直 ou faille de sécurité presque certain. Bloquez la compilation. Corrigez immédiatement. Exemple : SC2148, shebang manquant ; SC2070, $? non entouré de guillemets.
  • warning — Construction à haut risque, souvent exploitable. Bloquez la compilation. Corrigez-la ou justifiez explicitement sa désactivation. Exemple : SC2086, variable non entourée de guillemets.
  • info — Probablement correcte aujourd’hui, mais fragile ou non portable. Corrigez-la dans le même PR, sauf si elle est déclarée hors portée.
  • style — Préférence esthétique ou POSIX. Recommandée, mais facultative dans une base de code Bash pure.

Utilisez --severity=warning pour obtenir une valeur de sortie différente de zéro uniquement en présence d’avertissements ou de niveaux supérieurs — le seuil standard d’une barrière de sécurité :

#!/usr/bin/env bash
# gate.sh — fail CI on errors and warnings only
shellcheck --severity=warning scripts/*.sh
echo "ShellCheck exit code: $?"

Intégrer ShellCheck comme barrière de sécurité de l’intégration continue

Une barrière de sécurité n’est utile que si elle est obligatoire et automatisée. Le modèle ci-dessous encapsule ShellCheck dans une étape d’intégration continue qui :

  • Recherche chaque fichier .sh du dépôt.
  • Exécute ShellCheck avec --severity=warning et une sortie JSON lisible par machine.
  • Échoue la chaîne de traitement (exit 1) si le moindre résultat est détecté.
  • Affiche un résumé afin que les ingénieurs puissent traiter les résultats sans quitter le journal de l’intégration continue.

Déposez ce fichier dans votre dépôt et appelez-le depuis votre chaîne de traitement d’intégration continue (GitHub Actions, Jenkins, GitLab CI, etc.) :

#!/usr/bin/env bash
# ci/shellcheck_gate.sh
set -euo pipefail

SCRIPTS=$(find . -name '*.sh' -not -path './.git/*')
FAILED=0

for script in $SCRIPTS; do
  echo "==> Checking: $script"
  if ! shellcheck --severity=warning --format=tty "$script"; then
    FAILED=1
  fi
done

if [ "$FAILED" -eq 1 ]; then
  echo "[GATE] ShellCheck found warnings or errors. Build blocked." >&2
  exit 1
fi

echo "[GATE] All scripts passed ShellCheck."

La famille SC2086&nbsp;: expansions de variables non entourées de guillemets

SC2086 est le résultat le plus fréquent de ShellCheck et l’une des vulnérabilités du shell les plus exploitées : les expansions de variables non entourées de guillemets.

Lorsqu’une variable n’est pas entourée de guillemets doubles, le shell effectue un découpage des mots (en fonction de IFS) et une expansion des caractères génériques sur sa valeur. Un attaquant qui contrôle la variable peut injecter des arguments supplémentaires, déclencher une traversée du système de fichiers ou amener des commandes à recevoir des opérandes inattendus.

Modèle classique dangereux :

#!/usr/bin/env bash
# Attacker sets: FILENAME="important.txt /etc/passwd"
FILENAME="$1"

# UNSAFE — word splitting turns this into two args
rm $FILENAME

# SAFE — double quotes prevent splitting
rm "$FILENAME"

# Arrays are the right tool for lists
FILES=("$@")
rm -- "${FILES[@]}"

Détecter le risque d’injection de commandes avec SC2046 et SC2035

Deux règles moins connues, mais essentielles, traitent de l’injection de commandes via la sortie d’un sous-shell :

  • SC2046 — Entourez ceci de guillemets pour empêcher le découpage des mots et l’expansion des caractères génériques dans $(…). Si la sortie d’un sous-shell est utilisée sans guillemets, tout espace ou caractère générique de cette sortie devient un élément syntaxique du shell.
  • SC2035 — Utilisez ./*.sh plutôt que *.sh afin d’éviter que les noms de fichiers commençant par - soient interprétés comme des options (un vecteur classique d’injection d’arguments).

Scénario d’exploitation concret et correctif :

#!/usr/bin/env bash
# SC2046 example — output of find fed unquoted to chmod
# If a filename contains spaces, extra arguments appear

# UNSAFE
chmod 600 $(find /secrets -name '*.key')

# SAFE — use a while-read loop or xargs with -0
find /secrets -name '*.key' -print0 \
  | xargs -0 chmod 600

# SC2035 example
# UNSAFE — a file named '-rf' would be passed as an option
rm *.sh

# SAFE
rm -- ./*.sh

Utiliser le format de sortie JSON pour l’automatisation

ShellCheck prend en charge plusieurs formats de sortie via --format :

  • tty (par défaut) — sortie de terminal lisible par une personne
  • json — lisible par machine ; idéal pour les tableaux de bord, les blocages personnalisés ou l’envoi vers des plateformes SAST
  • gcc — compatible avec les outils qui analysent le format d’erreur de GCC (IDE, Vim/Emacs)
  • checkstyle — format XML consommé par le module Checkstyle de Jenkins

Le format JSON vous permet d’écrire des politiques automatisées, par exemple de bloquer uniquement sur des codes SC précis ou d’agréger les résultats d’une grande base de code dans un rapport de sécurité.

#!/usr/bin/env bash
# Emit JSON and filter for only error-severity findings using jq
shellcheck --format=json scripts/deploy.sh \
  | jq '[.[] | select(.level == "error")]'

# Count distinct SC codes across all scripts
find . -name '*.sh' -print0 \
  | xargs -0 shellcheck --format=json 2>/dev/null \
  | jq '[.[] | .code] | group_by(.) | map({code: .[0], count: length}) | sort_by(-.count)'

Désactiver correctement les faux positifs

La désactivation générale de ShellCheck va à l’encontre de son objectif. La bonne approche consiste à utiliser une désactivation ciblée et documentée, qui ne s’applique qu’à la ligne ou au bloc exact où le résultat ne s’applique réellement pas.

Trois mécanismes de désactivation :

  • Désactivation en ligne — # shellcheck disable=SC2086 sur la ligne précédant le code problématique. Elle ne s’applique qu’à cette ligne.
  • Désactivation/réactivation d’un bloc — entourez une section avec # shellcheck disable=… et # shellcheck enable=….
  • Directive au niveau du fichier — placez # shellcheck disable=… au début du fichier (rarement justifié ; documentez la raison).

Toute désactivation doit être accompagnée d’un commentaire expliquant pourquoi le résultat est un faux positif :

#!/usr/bin/env bash
# deploy.sh

# Legitimate suppression: $DEPLOY_ARGS is intentionally word-split
# because it is a pre-validated list of flags from a trusted config file.
# shellcheck disable=SC2086
exec deploy-tool $DEPLOY_ARGS

# Block suppression for a section that generates dynamic code
# shellcheck disable=SC2016
VARS='$HOME $PATH $USER'
echo "Unexpanded vars: $VARS"
# shellcheck enable=SC2016

Configurer ShellCheck avec .shellcheckrc

Pour les paramètres propres au projet, ShellCheck recherche .shellcheckrc depuis le répertoire du script, en remontant jusqu’à /. Cela vous évite de répéter les options à chaque invocation et simplifie les scripts de la barrière.

Directives utiles dans .shellcheckrc :

  • shell=bash — remplace la détection du dialecte (utile pour les fichiers sans shebang)
  • enable=all — active les vérifications facultatives (par exemple avoid-nullary-conditions, require-variable-braces)
  • disable=SC2059 — désactivation à l’échelle du projet pour une exception justifiée
  • external-sources=true — suit et vérifie les directives source / .
# .shellcheckrc — project root
shell=bash
enable=all
external-sources=true

# SC2312: consider invoking this command separately to avoid masking its
# return value — suppressed project-wide because we use set -e.
# Rationale: errexit already aborts on failure; masking risk is mitigated.
disable=SC2312

Script renforcé de bout en bout&nbsp;: avant et après

La manière la plus efficace d’assimiler les résultats de ShellCheck consiste à remanier un script réaliste, en le faisant passer d’un état en échec à un état propre et renforcé. Le script ci-dessous sauvegarde un répertoire et a été écrit sans tenir compte de la sécurité. Il échoue à au moins cinq règles distinctes de ShellCheck.

Étudiez les deux versions. La version après réussit shellcheck --severity=warning sans directives de désactivation et est nettement plus sûre face à des entrées contrôlées par un attaquant :

#!/usr/bin/env bash
# BEFORE — multiple ShellCheck violations
DEST=$1
SRC=$2
DATE=`date +%Y%m%d`

if [ ! -d $DEST ]; then
  mkdir $DEST
fi

cp -r $SRC $DEST/$DATE
echo Done


#!/usr/bin/env bash
# AFTER — ShellCheck-clean and hardened
set -euo pipefail

DEST="${1:?Usage: backup.sh <dest> <src>}"
SRC="${2:?Usage: backup.sh <dest> <src>}"
DATE=$(date +%Y%m%d)

if [ ! -d "$DEST" ]; then
  mkdir -p -- "$DEST"
fi

cp -r -- "$SRC" "$DEST/$DATE"
echo 'Done' >&2

Vérification des connaissances&nbsp;: ShellCheck dans une barrière de sécurité

Testez votre compréhension du rôle de ShellCheck en tant que barrière de sécurité.

Récapitulatif&nbsp;: l’analyse statique comme barrière de sécurité

Dans cette leçon, vous avez appris à faire de ShellCheck une barrière de sécurité obligatoire dans votre flux de travail Bash :

  • ShellCheck effectue une analyse statique sans exécuter vos scripts, et détecte les erreurs de guillemets, les risques d’injection et les constructions dangereuses avant l’exécution.
  • Chaque résultat comporte un code SC (par exemple SC2086) associé à une documentation détaillée et à des conseils de correction.
  • L’échelle de gravité — error, warning, info, style — permet d’ajuster la barrière : --severity=warning est le seuil de sécurité recommandé.
  • Utilisez une sortie lisible par machine (--format=json) pour automatiser les rapports, le suivi des tendances et l’intégration SAST.
  • Désactivez avec parcimonie : ciblez toujours une seule ligne, expliquez toujours la raison dans un commentaire et ne désactivez jamais globalement, sauf si cela est justifié par .shellcheckrc.
  • Associez ShellCheck à set -euo pipefail, à un guillemetage explicite, aux terminateurs -- argument et à la validation des entrées pour une défense en profondeur.

Un script qui réussit ShellCheck n’est pas automatiquement sécurisé — mais un script qui échoue à ShellCheck ne devrait jamais atteindre la production.

Questions Fréquemment Posées

La leçon « Analyse statique et audit avec ShellCheck » est-elle gratuite ?

Oui — le texte complet de « Analyse statique et audit avec ShellCheck » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Linux Command Line & Bash Scripting Mastery, passe à CoddyKit PRO. Le cours Linux Command Line & Bash Scripting Mastery comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Analyse statique et audit avec ShellCheck » ?

Intégrez ShellCheck à une barrière de sécurité et interprétez ses résultats pour renforcer chaque script. Tu pratiques Linux Command Line & Bash Scripting Mastery avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Linux Command Line & Bash Scripting Mastery ?

Aucune expérience préalable n'est requise. Linux Command Line & Bash Scripting Mastery sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Analyse statique et audit avec ShellCheck » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Linux Command Line & Bash Scripting Mastery ?

Oui. Chaque leçon Linux Command Line & Bash Scripting Mastery inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Prévenir l’injection de commandes et d’arguments
  2. Gérer les secrets en toute sécurité et assainir l’environnement
  3. Exécuter avec le principe du moindre privilège et discipliner sudo
  4. Analyse statique et audit avec ShellCheck
← Retour à Linux Command Line & Bash Scripting Mastery