← retour aux snippets

bash: history sécurisé et effacement ciblé

Éviter d'enregistrer des secrets, effacer une ligne, sessions éphémères, timestamps et droits du fichier.

bash sécurité #bash#history#security#cli

objectif

Empêcher l’enregistrement de commandes sensibles (tokens, mots de passe), supprimer une entrée précise de l’historique, lancer des sessions sans historique et sécuriser le fichier ~/.bash_history. Exemples avec api.data.pm.

code minimal

# ne pas enregistrer la commande suivante (prefixe espace + ignoreboth)
HISTCONTROL=ignoreboth
 export API_TOKEN="$(openssl rand -hex 32)"

# effacer la précédente commande de l'historique (puis réécrire le fichier)
history -d $((HISTCMD-1)); history -w

utilisation

# 1) config de base (~/.bashrc) : sécurité et confort
grep -q 'HISTCONTROL' ~/.bashrc || cat >> ~/.bashrc <<'BASH'
# history: ignorer doublons + lignes qui commencent par un espace
export HISTCONTROL=ignoreboth
# taille raisonnable
export HISTSIZE=5000
export HISTFILESIZE=50000
# timestamps
export HISTTIMEFORMAT='%F %T '
# ne pas enregistrer des commandes triviales
export HISTIGNORE='ls:cd:pwd:clear:history *:exit'
# permissions strictes
[ -f "$HISTFILE" ] && chmod 600 "$HISTFILE" 2>/dev/null || true
BASH

# 2) saisir un secret sans qu'il apparaisse à l'écran ni dans l'historique
read -s -p 'API token: ' API_TOKEN; echo
# utiliser le token sans le logguer (prefixe espace pour ne pas logguer la commande)
 curl -fsS -H "Authorization: Bearer $API_TOKEN" https://api.data.pm/v1/me -o /dev/null

# 3) effacer une entrée précise par numéro (trouvé via history | nl)
history | tail -n 20
# supprimer la ligne 1234, puis réécrire sur disque
history -d 1234; history -w

# 4) supprimer toutes les entrées contenant un motif (ex: "Authorization")
tmp="$(mktemp)"; { grep -v 'Authorization' "$HISTFILE" || true; } > "$tmp" \
  && chmod 600 "$tmp" && mv -f "$tmp" "$HISTFILE"
# recharger en mémoire
history -c; history -r

# 5) session éphémère sans historique (shell enfant)
HISTFILE=/dev/null HISTSIZE=0 HISTFILESIZE=0 bash -l

# 6) append immédiat et relecture (multi-terminaux plus fiables)
export PROMPT_COMMAND='history -a; history -n'

variante(s) utile(s)

# ne jamais enregistrer les lignes qui contiennent un mot-clé (hook simple)
block_hist() {
  case "$BASH_COMMAND" in
    *API_TOKEN*|*Authorization*|*password* ) history -d $((HISTCMD)) 2>/dev/null || true ;;
  esac
}
trap block_hist DEBUG

# vider complètement l'historique courant et le fichier (irréversible)
history -c
: > "$HISTFILE"
history -w

# protéger le fichier d'historique (droits et appartenance)
install -m 0600 /dev/null "$HOME/.bash_history" 2>/dev/null || true
chown "$USER":"$USER" "$HOME/.bash_history" 2>/dev/null || true

# éviter d'exposer un secret en argument: passer par stdin/vars
# (ex: POST sur api.data.pm sans mettre le token dans l'historique)
 read -s -p 'API token: ' API_TOKEN; echo
 jq -n --arg t "$API_TOKEN" '{token:$t}' \
  | curl -fsS -X POST https://api.data.pm/v1/tokens/verify \
      -H 'Content-Type: application/json' --data-binary @-

# ignorer aussi l'historique pour des commandes spécifiques ad hoc
HISTIGNORE="$HISTIGNORE:curl *Authorization*:*API_TOKEN*"

notes

  • HISTCONTROL=ignoreboth combine ignorespace (les lignes commençant par un espace ne sont pas enregistrées) et ignoredups.
  • history -d <n> supprime la ligne <n> de l’historique en mémoire; history -w réécrit le fichier. Utilisez history -c; history -r pour recharger après édition du fichier.
  • read -s masque la saisie; préférez des variables et l’entrée standard plutôt que des arguments en clair.
  • sécurisez ~/.bash_history en 0600. L’historique n’est pas une barrière de sécurité absolue: évitez de taper des secrets en clair.
  • pour des environnements partagés, combinez avec des politiques de shell sécurisé et évitez le scrollback du terminal lors de la saisie de secrets.