Statisk analyse og revisjon med ShellCheck
Integrer ShellCheck i en sikkerhetskontroll, og tolk funnene for å sikre hvert skript bedre.
Statisk analyse og revisjon med ShellCheck er en gratis leksjon i Mestring av Linux-kommandolinjen og Bash-skripting på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Mestring av Linux-kommandolinjen og Bash-skripting, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Mestring av Linux-kommandolinjen og Bash-skripting inneholder totalt 4 leksjoner.
Hva er ShellCheck, og hvorfor er det viktig
ShellCheck er et åpen kildekode-verktøy for statisk analyse av shell-skript. Det analyserer Bash-kildekode (samt POSIX sh, dash og ksh) uten å kjøre den, og rapporterer feil, usikre konstruksjoner, portabilitetsproblemer og stilproblemer – hvert funn er merket med en unik regelkode, for eksempel SC2086.
I en sikkerhetsherdet prosess fungerer ShellCheck som en obligatorisk kontroll: Ingen skript leveres før de består kontrollen. Dette er viktig fordi:
- Mange sårbarheter i shell (orddeling, injeksjon og anførselstegn rundt utvidelser som mangler) er usynlige ved testing av normale tilfeller, men utløses av angriperkontrollerte inndata.
- ShellCheck oppdager disse feiltypene før kjøring, uten kostnad.
- Det dokumenterer hvorfor hvert mønster er farlig, slik at teamet gradvis blir mer bevisst.
Installer det på et hvilket som helst system:
# 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 --versionKjøre ShellCheck for første gang
Den enkleste måten å starte på er shellcheck <script>. ShellCheck leser shebang-linjen for å finne shell-dialekten og skriver deretter funnene til stdout.
Hvert funn inneholder:
- Fil- og linjenummer – nøyaktig plassering
- Alvorlighetsgrad –
error,warning,infoellerstyle - SC-kode – en stabil regelidentifikator som De kan slå opp eller undertrykke
- Forklaring i klartekst – forteller hva som er galt, og ofte hvordan det kan rettes
Kjør skriptet nedenfor og se hvilken utdata ShellCheck ville produsert:
#!/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 -lTolke ShellCheck-utdata og SC-koder
For skriptet i forrige scene ville ShellCheck rapportert funn som:
SC2086(warning) – Double quote to prevent globbing and word splitting – for$FILEi[ $FILE == '' ]og icat $FILE.SC2039/SC3010(info) – == in [ ] is a bashism; use = for POSIX.SC2002(style) – Useless cat. Consider cmd < file instead of cat file | cmd.
Hver SC-kode viser til en wikiside på https://www.shellcheck.net/wiki/SCxxxx med begrunnelse og et korrigert eksempel.
Den korrigerte versjonen av skriptet:
#!/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"Alvorlighetsgrader og hva De bør gjøre noe med
ShellCheck klassifiserer hvert funn etter alvorlighetsgrad. I en sikkerhetskontroll bør De behandle dem slik:
- error – Nesten sikkert en feil eller et sikkerhetshull. Stans byggingen. Rett det umiddelbart. Eksempel:
SC2148manglende shebang,SC2070$?uten anførselstegn. - warning – Et høyrisikomønster som ofte kan utnyttes. Stans byggingen. Rett det, eller begrunn uttrykkelig hvorfor funnet undertrykkes. Eksempel:
SC2086variabel uten anførselstegn. - info – Sannsynligvis korrekt i dag, men skjørt eller ikke-portabelt. Rett det i samme PR, med mindre det uttrykkelig er utenfor omfanget.
- style – Kosmetikk eller POSIX-preferanse. Anbefalt, men valgfritt i en ren Bash-kodebase.
Bruk --severity=warning for å avslutte med en feilkode bare ved advarsler eller høyere alvorlighetsgrad – standardterskelen for sikkerhetskontrollen:
#!/usr/bin/env bash
# gate.sh — fail CI on errors and warnings only
shellcheck --severity=warning scripts/*.sh
echo "ShellCheck exit code: $?"Integrere ShellCheck som en sikkerhetskontroll i CI
En sikkerhetskontroll er bare nyttig når den er obligatorisk og automatisert. Mønsteret nedenfor pakker ShellCheck inn i et CI-trinn som:
- Finner alle
.sh-filer i repositoriet. - Kjører ShellCheck med
--severity=warningog maskinlesbar JSON-utdata. - Får pipelinen til å feile (
exit 1) hvis det finnes et funn. - Skriver ut et sammendrag, slik at utviklere kan håndtere funnene uten å forlate CI-loggen.
Legg denne filen i repositoriet og kall den fra CI-pipelinen (GitHub Actions, Jenkins, GitLab CI osv.):
#!/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."SC2086-familien: Variabelutvidelser uten anførselstegn
SC2086 er det vanligste ShellCheck-funnet og en av de mest utnyttede sårbarhetene i shell: variabelutvidelser uten anførselstegn.
Når en variabel ikke står i doble anførselstegn, utfører skallet orddeling (deler ved IFS) og jokertegnutvidelse av verdien. En angriper som kontrollerer variabelen, kan injisere ekstra argumenter, utløse katalogkryssing eller få kommandoer til å motta uventede operander.
Klassisk farlig mønster:
#!/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[@]}"Oppdage risiko for kommandoinjeksjon med SC2046 og SC2035
To mindre kjente, men kritiske regler gjelder kommandoinjeksjon via utdata fra underskall:
SC2046– Quote this to prevent word splitting / glob i$(…). Hvis utdata fra et underskall brukes uten anførselstegn, blir alle mellomrom eller jokertegn i utdataene til shell-tokener.SC2035– Use./*.shinstead of*.shfor å unngå at filnavn som begynner med-, tolkes som alternativer (en klassisk vektor for argumentinjeksjon).
Konkret scenario for utnyttelse og løsning:
#!/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 -- ./*.shBruke JSON-utdataformatet til automatisering
ShellCheck støtter flere utdataformater via --format:
tty(standard) – terminalutdata som er lesbare for menneskerjson– maskinlesbart; ideelt for dashbord, tilpassede blokkeringer eller opplasting til SAST-plattformergcc– kompatibelt med verktøy som analyserer GCC-feilformatet (IDE-er, Vim/Emacs)checkstyle– XML-format som brukes av Jenkins Checkstyle-plugin
JSON-formatet lar Dem skrive automatiserte regler, for eksempel blokkere bare ved bestemte SC-koder eller samle funn fra en stor kodebase i en sikkerhetsrapport.
#!/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)'Undertrykke falske positiver på riktig måte
En generell deaktivering av ShellCheck undergraver hensikten med verktøyet. Den riktige tilnærmingen er en målrettet og dokumentert undertrykking som bare påvirker den nøyaktige linjen eller blokken der funnet faktisk ikke gjelder.
Tre mekanismer for undertrykking:
- Deaktivering på én linje –
# shellcheck disable=SC2086på linjen over den aktuelle koden. Gjelder bare den linjen. - Deaktivering/aktivering av blokk – omslutt en del med
# shellcheck disable=…og# shellcheck enable=…. - Direktiv på filnivå – plasser
# shellcheck disable=…øverst i filen (sjelden berettiget; dokumenter hvorfor).
Hver undertrykking må ha en kommentar som forklarer hvorfor funnet er en falsk positiv:
#!/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=SC2016Konfigurere ShellCheck via .shellcheckrc
For innstillinger som gjelder hele prosjektet leser ShellCheck .shellcheckrc fra skriptets katalog og oppover til /. Dette gjør at De slipper å gjenta flagg ved hvert kall, og holder kontrollskriptene enkle.
Nyttige direktiver i .shellcheckrc:
shell=bash– overstyr dialektgjenkjenningen (nyttig for filer uten shebang)enable=all– aktiver valgfrie kontroller (for eksempelavoid-nullary-conditions,require-variable-braces)disable=SC2059– prosjektomfattende undertrykking for et begrunnet unntakexternal-sources=true– følg og kontrollersource- og.-direktiver
# .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=SC2312Herdet skript fra start til slutt: før og etter
Den mest effektive måten å få grep om ShellCheck-funn på er å refaktorere et realistisk skript fra en tilstand som feiler, til et rent og herdet skript. Skriptet nedenfor sikkerhetskopierer en katalog og ble skrevet uten sikkerhet i tankene. Det feiler i ShellCheck på minst fem ulike regler.
Studer begge versjonene. Etter-versjonen består shellcheck --severity=warning uten undertrykkingsdirektiver og er betydelig sikrere ved angriperkontrollerte inndata:
#!/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' >&2Kunnskapssjekk: ShellCheck som sikkerhetskontroll
Test forståelsen Deres av ShellChecks rolle som sikkerhetskontroll.
Oppsummering: Statisk analyse som sikkerhetskontroll
I denne leksjonen har De lært hvordan De gjør ShellCheck til en obligatorisk sikkerhetskontroll i Bash-arbeidsflyten:
- ShellCheck utfører statisk analyse uten å kjøre skriptene, og oppdager siteringsfeil, injeksjonsrisiko og usikre mønstre før kjøring.
- Hvert funn har en SC-kode (for eksempel
SC2086) med lenke til detaljert dokumentasjon og veiledning for retting. - Alvorlighetsstigen –
error,warning,info,style– lar Dem kalibrere kontrollen:--severity=warninger den anbefalte sikkerhetsterskelen. - Bruk maskinlesbare utdata (
--format=json) til å automatisere rapportering, følge utviklingen over tid og integrere med SAST. - Undertrykk sparsomt: målrett alltid én enkelt linje, dokumenter alltid hvorfor i en kommentar, og undertrykk aldri globalt med mindre det er begrunnet i
.shellcheckrc. - Kombiner ShellCheck med
set -euo pipefail, eksplisitt bruk av anførselstegn,-- argument-avslutning og validering av inndata for et forsvar i dybden.
Et skript som består ShellCheck, er ikke automatisk sikkert – men et skript som ikke består ShellCheck, bør aldri nå produksjon.
Lær deg Bash med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 22
- Leksjoner
- 88
Ofte stilte spørsmål
Er leksjonen «Statisk analyse og revisjon med ShellCheck» gratis?
Ja – hele teksten i «Statisk analyse og revisjon med ShellCheck» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Mestring av Linux-kommandolinjen og Bash-skripting-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Mestring av Linux-kommandolinjen og Bash-skripting inneholder totalt 4 leksjoner.
Hva lærer jeg i «Statisk analyse og revisjon med ShellCheck»?
Integrer ShellCheck i en sikkerhetskontroll, og tolk funnene for å sikre hvert skript bedre. Du øver på Mestring av Linux-kommandolinjen og Bash-skripting med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Mestring av Linux-kommandolinjen og Bash-skripting?
Ingen tidligere erfaring er nødvendig. Mestring av Linux-kommandolinjen og Bash-skripting på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.
Hvor lang tid tar leksjonen «Statisk analyse og revisjon med ShellCheck»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Mestring av Linux-kommandolinjen og Bash-skripting-leksjonen?
Ja. Alle Mestring av Linux-kommandolinjen og Bash-skripting-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Forebygging av kommando- og argumentinjisering
- Sikker håndtering av hemmeligheter og ryddige miljøer
- Kjøring med minste privilegium og sudo-disiplin
- Statisk analyse og revisjon med ShellCheck