Gérer les secrets en toute sécurité et assainir l’environnement
Évitez d’exposer les identifiants dans les listes de processus et les journaux en utilisant l’entrée standard, des fichiers et des environnements nettoyés.
Gérer les secrets en toute sécurité et assainir l’environnement est une leçon Linux Command Line & Bash Scripting Mastery gratuite sur CoddyKit. Ceci est la leçon 2 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.
Pourquoi l’hygiène des secrets est importante
Les secrets — clés d’API, mots de passe, jetons — sont les données les plus sensibles de tout système. Une mauvaise gestion dans les scripts Bash constitue l’une des erreurs de sécurité les plus fréquentes et les plus dommageables.
- Listes des processus : les arguments transmis aux commandes apparaissent dans
ps aux,/proc/<pid>/cmdlineet les journaux d’audit du système ; ils sont visibles par tous les utilisateurs de l’hôte. - Historique du shell : les commandes saisies de manière interactive (et parfois les scripts) sont enregistrées dans
~/.bash_history. - Fichiers journaux : les traces de
set -x, les journaux des applications et les sorties de l’intégration et du déploiement continus peuvent capturer les valeurs des variables. - Fuite par l’environnement : les processus enfants héritent de l’environnement complet de leur parent, y compris les secrets exportés.
Un script renforcé traite les secrets comme une matière radioactive : minimiser la durée d’exposition, limiter la surface concernée et tout assainir lors de la sortie.
La surface d’attaque liée à la liste des processus
Lorsque vous transmettez un secret comme argument de ligne de commande, tous les utilisateurs du système peuvent le lire immédiatement via ps. Ce n’est pas théorique : cette méthode est régulièrement exploitée dans les environnements d’hébergement partagé et de conteneurs.
L’extrait ci-dessous présente le problème et sa correction côte à côte.
#!/usr/bin/env bash
# DANGEROUS: password visible in 'ps aux' output
# curl -u "admin:SuperSecret123" https://api.example.com/data
# SAFE: pass credentials via stdin or a flag that reads from a file
# Many tools support reading secrets from stdin with '-' or dedicated flags:
# Option 1 — pipe the secret so it never appears in argv
echo 'SuperSecret123' | curl -u 'admin' --password-stdin \
https://api.example.com/data 2>/dev/null || true
# Option 2 — write a temporary netrc and point curl at it
# (covered in a later scene)
echo 'Secret never touches the command line this way'Lire les secrets depuis l’entrée standard
La méthode interactive la plus sûre consiste à lire un secret au moment de l’exécution avec read -rs. L’option -s désactive l’écho afin que les caractères ne soient jamais affichés, tandis que -r empêche l’interprétation des barres obliques inverses.
Points clés :
- La variable n’est jamais exportée ; les processus enfants ne peuvent donc pas la voir via
/proc/<pid>/environ. - Après utilisation, supprimez immédiatement la variable avec
unsetafin de réduire la fenêtre d’exposition. - Évitez
echo "$SECRET"— utilisezprintf '%s'pour empêcher qu’un saut de ligne final ne corrompe la valeur et pour qu’elle reste invisible dans les traces.
#!/usr/bin/env bash
set -euo pipefail
# Prompt on stderr so stdout stays clean for piping
read -rsp 'Enter API token: ' API_TOKEN <&2
printf '\n' >&2
# Use the secret — printf keeps it out of argv
response=$(printf '%s' "$API_TOKEN" | curl -sS -X POST \
-H 'Content-Type: application/json' \
--data-binary @- \
https://httpbin.org/post 2>/dev/null) || true
echo "Request sent."
# Scrub immediately — unset removes it from shell memory
unset API_TOKENSecrets dans les fichiers : permissions et propriété
Lorsqu’un secret doit être conservé sur le disque (par exemple, une clé de compte de service), les permissions du fichier constituent votre première ligne de défense.
- Mode 0600 — lisible et modifiable uniquement par le propriétaire. Aucun accès pour le groupe ni pour les autres utilisateurs.
- Mode 0400 — accessible en lecture seule par le propriétaire. Privilégiez ce mode pour les clés que vous ne devez jamais écraser accidentellement.
- Stockez les fichiers de secrets dans un répertoire dédié, tel que
~/.secrets/ou/run/secrets/(ce dernier est un tmpfs reposant sur la RAM dans de nombreux systèmes Linux et ne subsiste que jusqu’au redémarrage). - Ne placez jamais de fichiers de secrets dans un répertoire suivi par git sans un fichier
.gitignoreparfaitement fiable.
#!/usr/bin/env bash
set -euo pipefail
SECRETS_DIR="${HOME}/.secrets"
mkdir -p "$SECRETS_DIR"
chmod 700 "$SECRETS_DIR" # directory: only owner can list contents
KEY_FILE="${SECRETS_DIR}/api_token"
# Write secret — atomically restrict permissions before writing content
install -m 0600 /dev/null "$KEY_FILE"
printf '%s' 'my-super-secret-token' > "$KEY_FILE"
echo "Permissions:"
ls -la "$KEY_FILE"
# Read back safely — no subshell, no echo
API_TOKEN=$(< "$KEY_FILE")
echo "Token length: ${#API_TOKEN} chars (value not printed)"
unset API_TOKENUtiliser un fichier .netrc avec curl
curl prend en charge un fichier ~/.netrc (ou un chemin quelconque indiqué via --netrc-file) qui associe des noms d’hôte à des identifiants. Les données d’authentification restent ainsi complètement absentes de la ligne de commande et du corps du script.
Le format du fichier est simple :
machine api.example.com
login admin
password s3cr3tBonnes pratiques :
- Définissez toujours
chmod 0600 ~/.netrc— curl refuse le fichier s’il est lisible par tous sur certains systèmes. - Utilisez
--netrc-file /run/secrets/netrcpour désigner un secret reposant sur un tmpfs ou injecté dans un conteneur. - Supprimez les fichiers netrc temporaires avec un
trapsur EXIT.
#!/usr/bin/env bash
set -euo pipefail
TMP_NETRC=$(mktemp)
chmod 0600 "$TMP_NETRC"
# Trap ensures cleanup even on error or signal
trap 'rm -f "$TMP_NETRC"' EXIT
# Write credentials to the temp netrc
cat > "$TMP_NETRC" <<'EOF'
machine httpbin.org
login myuser
password mypassword
EOF
curl -fsS --netrc-file "$TMP_NETRC" \
https://httpbin.org/basic-auth/myuser/mypassword \
-o /dev/null -w 'HTTP %{http_code}\n' || true
# trap fires here: $TMP_NETRC is deleted
echo 'Temp netrc cleaned up by trap.'Hygiène des variables d’environnement
Les variables d’environnement sont un moyen courant d’injecter des secrets dans les scripts (applications 12 facteurs, chaînes CI/CD). Cependant, elles sont transmises à chaque processus fils et apparaissent dans /proc/<pid>/environ pendant toute la durée de vie du processus.
Mesures défensives :
- Importez immédiatement le secret dans une variable locale et annulez la variable d’environnement afin que les processus fils ne puissent pas en hériter.
- Transmettez les secrets aux commandes concernées à l’aide de
env -iou d’une affectation en ligne, plutôt qu’au moyen de l’environnement entièrement hérité. - N’
exportez jamais une variable contenant un secret — utilisez si possible une affectation seule (sansexport).
#!/usr/bin/env bash
set -euo pipefail
# Simulate a secret arriving via environment (e.g., from CI system)
export DB_PASSWORD='hunter2' # set by CI — we did not choose this
# Capture locally, then strip from environment immediately
db_password="$DB_PASSWORD"
unset DB_PASSWORD
# Verify the env var is gone before spawning any child process
if printenv DB_PASSWORD 2>/dev/null; then
echo 'ERROR: DB_PASSWORD still in environment!' >&2
exit 1
fi
echo 'Secret captured and env var scrubbed.'
echo "Password length: ${#db_password}"
unset db_passwordEmpêcher l’apparition des secrets dans les traces de set -x
set -x (xtrace) est extrêmement utile pour le débogage, mais affiche sur stderr la valeur de chaque variable qu’il développe — y compris les secrets. Ces traces finissent souvent dans les journaux CI ou syslog.
Stratégies pour protéger les secrets tout en conservant des traces utiles :
- Désactivez temporairement les traces autour des opérations sensibles avec
{ set +x; } 2>/dev/null. - Réactivez-les ensuite avec
set -x. - Redirigez la sortie xtrace vers un descripteur de fichier distinct qui pointe vers un fichier journal protégé, et non vers le flux de journal public.
#!/usr/bin/env bash
set -euo pipefail
set -x # tracing ON — safe for non-sensitive sections
echo 'Building application...'
SRC_DIR='/tmp/build'
mkdir -p "$SRC_DIR"
# Disable xtrace around secret handling (suppress the set +x line itself)
{ set +x; } 2>/dev/null
read -rsp 'Token (hidden from trace): ' SECRET_TOKEN <&2
printf '\n' >&2
token_len=${#SECRET_TOKEN}
unset SECRET_TOKEN
set -x # tracing back ON
echo "Token captured (length=$token_len). Continuing build..."
ls "$SRC_DIR"Nettoyage des secrets dans les fichiers journaux
Même lorsque vous êtes prudent, des secrets se retrouvent parfois dans la sortie des journaux — en particulier dans les scripts verbeux ou anciens. Une fonction d’encapsulation de la journalisation qui masque les motifs connus ajoute un filet de sécurité.
Cette méthode utilise un remplacement fondé sur une expression régulière pour toute la sortie des journaux. Il s’agit d’une couche de dernier recours, et non d’un remplacement des autres pratiques d’hygiène déjà présentées.
#!/usr/bin/env bash
set -euo pipefail
# A logging function that scrubs common secret patterns before writing
log() {
local line
# Replace anything that looks like key=VALUE or password=VALUE
line=$(printf '%s\n' "$*" \
| sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***REDACTED***/gi')
printf '[%s] %s\n' "$(date -u '+%T')" "$line"
}
# Usage:
log 'Connecting to database with password=hunter2'
log 'Loaded API token=sk-abc123xyz secret'
log 'Build step completed successfully' # unchangedEnvironnements isolés avec env -i
env -i démarre une commande avec un environnement complètement vide, empêchant toute variable héritée — y compris les secrets transmis accidentellement — d’atteindre le processus fils. Vous transmettez ensuite explicitement uniquement ce qui est nécessaire.
C’est particulièrement utile pour exécuter des scripts non fiables, des outils de compilation ou des utilitaires tiers susceptibles d’exfiltrer les données d’environnement.
#!/usr/bin/env bash
set -euo pipefail
# Polluted parent environment (simulating a CI runner)
export AWS_SECRET_ACCESS_KEY='AKIAIOSFODNN7EXAMPLE'
export GITHUB_TOKEN='ghp_faketoken123'
export HOME="$HOME"
export PATH="$PATH"
echo '--- Child sees full environment:'
env | grep -E 'AWS|GITHUB' | head -5
echo '--- Sanitised child (env -i) sees nothing secret:'
env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-dumb}" \
bash -c 'env | grep -E "AWS|GITHUB" || echo "No secrets visible"'
unset AWS_SECRET_ACCESS_KEY GITHUB_TOKENFichiers de secrets temporaires sur tmpfs
tmpfs est un système de fichiers reposant sur la RAM. Les fichiers qui y sont écrits ne sont jamais vidés sur le disque, ce qui élimine le risque que des secrets subsistent dans l’espace d’échange, le cache disque ou des instantanés.
- Sous Linux,
/dev/shmet/run/user/<uid>sont généralement des montages tmpfs. - Associez toujours l’utilisation de tmpfs à un
trap EXITafin de supprimer les fichiers lorsque le script se termine. - Dans les conteneurs (Docker, Kubernetes), les secrets peuvent être montés directement comme volumes tmpfs dans
/run/secrets.
#!/usr/bin/env bash
set -euo pipefail
# Prefer /run/user/$UID (user-owned tmpfs) or /dev/shm (world-readable dir!)
if [[ -d "/run/user/$UID" ]]; then
TMPFS_DIR="/run/user/$UID"
elif [[ -d '/dev/shm' ]]; then
TMPFS_DIR='/dev/shm'
else
# Fallback: warn that disk will be used
echo 'WARNING: No tmpfs available; using /tmp (disk-backed)' >&2
TMPFS_DIR='/tmp'
fi
SECRET_FILE=$(mktemp "${TMPFS_DIR}/secret.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'shred -u "$SECRET_FILE" 2>/dev/null || rm -f "$SECRET_FILE"' EXIT
printf '%s' 'my-runtime-token' > "$SECRET_FILE"
echo "Secret stored in: $SECRET_FILE"
df -T "$SECRET_FILE" | awk 'NR==2 {print "Filesystem type:", $2}'
# Use the secret...
token=$(< "$SECRET_FILE")
echo "Token length: ${#token}"
unset token
# trap fires on exit: file shreddedTout mettre en pratique : un script de déploiement renforcé
Le script suivant combine toutes les techniques de cette leçon dans un assistant de déploiement réaliste. Observez comment chaque couche de défense renforce les autres :
- Lecture depuis stdin avec
-s— aucun écho dans le terminal - Fichier de secrets tmpfs avec nettoyage par
trap - Nettoyage de l’environnement — le secret est annulé avant tout sous-processus
- Protection contre xtrace — les traces sont suspendues autour du code sensible
- Masquage des journaux — expression régulière de sécurité avant l’écriture dans le journal
#!/usr/bin/env bash
set -euo pipefail
### 1. Redacting logger
log() {
local msg
msg=$(printf '%s' "$*" \
| sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***/gi')
printf '[%s] %s\n' "$(date -u +%T)" "$msg"
}
### 2. tmpfs secret store
TMPFS_DIR="${XDG_RUNTIME_DIR:-/tmp}"
SECRET_FILE=$(mktemp "${TMPFS_DIR}/deploy_token.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'rm -f "$SECRET_FILE"; log "Secret file cleaned up."' EXIT
### 3. Read secret without trace
{ set +x; } 2>/dev/null
read -rsp 'Deploy token: ' _tok <&2; printf '\n' >&2
printf '%s' "$_tok" > "$SECRET_FILE"
unset _tok
set -x
### 4. Scrub inherited env vars before subprocess
unset DEPLOY_TOKEN 2>/dev/null || true
log 'Starting deployment...'
# Simulate deploy using secret from file (token never in argv)
# curl -H "Authorization: Bearer $(< $SECRET_FILE)" https://api.example.com/deploy
log 'Deployment complete. token=hidden_by_redactor'
echo 'Done.'Vérification des connaissances : exposition des secrets via la liste des processus
Vérifiez votre compréhension de la manière dont les secrets sont divulgués dans les listes de processus et de la façon de l’empêcher.
Récapitulatif de la leçon : gestion sécurisée des secrets
Vous avez terminé Gestion sécurisée des secrets et hygiène de l’environnement. Voici une référence concise de tout ce qui a été abordé :
- Listes de processus : ne transmettez jamais de secrets comme arguments de ligne de commande — ils apparaissent dans
ps auxet/proc/<pid>/cmdline. Utilisez plutôt un acheminement via stdin ou--netrc-file. - Lectures depuis stdin : utilisez
read -rspour recueillir les secrets de manière interactive, sans écho dans le terminal ni exposition dans l’historique du shell. - Permissions des fichiers : les fichiers de secrets doivent être en
chmod 0600(ou0400). Utilisezinstall -m 0600pour une création atomique. - Fichiers netrc : déléguez les identifiants à un fichier temporaire désigné par
--netrc-file; supprimez-le avectrap EXIT. - Hygiène de l’environnement : utilisez immédiatement
unsetsur les variables d’environnement secrètes après les avoir capturées localement ; ne lesexportez jamais sans nécessité ; utilisezenv -ipour isoler les processus fils. - Protection contre xtrace : entourez le code sensible de
{ set +x; } 2>/dev/null ... set -xafin d’empêcher les traces de débogage de divulguer les valeurs. - Masquage des journaux : utilisez un outil de journalisation fondé sur
sedcomme filet de sécurité de dernier recours. - tmpfs : stockez les secrets d’exécution dans
/run/user/$UIDou/dev/shmafin qu’ils ne touchent jamais le disque ; détruisez-les à la sortie.
La défense en profondeur est l’état d’esprit essentiel : aucune mesure unique ne suffit, mais leur association rend la fuite de secrets extrêmement difficile.
Questions Fréquemment Posées
La leçon « Gérer les secrets en toute sécurité et assainir l’environnement » est-elle gratuite ?
Oui — le texte complet de « Gérer les secrets en toute sécurité et assainir l’environnement » 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 « Gérer les secrets en toute sécurité et assainir l’environnement » ?
Évitez d’exposer les identifiants dans les listes de processus et les journaux en utilisant l’entrée standard, des fichiers et des environnements nettoyés. 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 2 sur 4.
Combien de temps prend la leçon « Gérer les secrets en toute sécurité et assainir l’environnement » ?
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
- Prévenir l’injection de commandes et d’arguments
- Gérer les secrets en toute sécurité et assainir l’environnement
- Exécuter avec le principe du moindre privilège et discipliner sudo
- Analyse statique et audit avec ShellCheck