Aller au contenu
Sécurité medium

Bagel : scanner la posture sécurité de votre poste développeur

21 min de lecture

Votre poste de développement contient des clés SSH sans passphrase, des tokens GitHub en clair dans l’historique shell, des credentials AWS dans des fichiers .env et du SSL désactivé dans Git — et personne ne le vérifie. Bagel est un scanner open source qui inventorie ces risques en lecture seule, sans jamais exfiltrer les valeurs des secrets. Il produit un rapport structuré JSON avec des remédiations actionnables pour chaque finding.

Ce guide vous apprend à installer Bagel, lancer votre premier scan, interpréter les résultats et intégrer le scanner dans vos pipelines CI. Il s’adresse aux développeurs et aux équipes sécurité qui veulent auditer la posture de leurs postes de travail.

  • Ce qu’est Bagel et pourquoi scanner les postes développeurs
  • Les 9 sondes (probes) et les 8 détecteurs de secrets
  • Comment installer et lancer un premier scan
  • Comment interpréter et prioriser les findings
  • Les remédiations concrètes par type de problème
  • L’intégration CI avec le mode --strict

Bagel est une CLI cross-platform (macOS, Linux, Windows) développé en Go par BoostSecurity.io. Il inspecte le poste de travail d’un développeur et produit un rapport structuré des configurations risquées et des métadonnées de secrets — sans jamais collecter les valeurs réelles.

L’analogie est simple : Bagel fait pour votre poste développeur ce que Lynis fait pour un serveur Linux — un audit automatisé qui identifie les écarts par rapport aux bonnes pratiques de sécurité. La différence est que Bagel cible spécifiquement les outils de développement : Git, SSH, npm, cloud CLIs, IDEs, historique shell.

AspectDétail
ObjectifInventorier les configurations risquées et les secrets exposés sur les postes développeurs
ApprocheLecture seule — aucune modification, aucune exfiltration de secrets
Sondes9 probes : Git, SSH, npm, env, shell_history, cloud, JetBrains, GitHub CLI, AI CLI
Détecteurs8 : GitHub token, npm token, AI service, HTTP auth, SSH key, cloud credentials, generic API key, JWT
SortieJSON structuré ou table lisible
CIMode --strict (exit code 2 si findings détectés)
LicenceGPL-3.0
LangageGo

Les attaques supply chain modernes ciblent de plus en plus les postes de développement plutôt que les serveurs de production. Un poste développeur compromis donne accès à :

  • Le code source — repos privés, propriété intellectuelle, secrets hardcodés
  • L’infrastructure — credentials AWS/GCP/Azure, accès Kubernetes, consoles cloud
  • La supply chain — tokens npm/PyPI pour publier des packages malveillants, accès aux pipelines CI/CD

Les risques les plus courants sont invisibles au quotidien :

RisqueExempleImpact
Clé SSH sans passphrase~/.ssh/id_ed25519 non chiffréeAccès à tous les serveurs et repos Git si le poste est compromis
Token dans l’historique shellexport GITHUB_TOKEN=ghp_... dans .zsh_historyExtraction triviale par un malware ou un script malveillant
SSL désactivé dans Githttp.sslVerify=falseAttaque man-in-the-middle sur les pulls/pushes
Credentials cloud en clair~/.aws/credentials avec access keyAccès complet au compte AWS
Credentials dans .envAPI_KEY=sk-... en clairExposition via un commit accidentel ou un accès fichier

Bagel automatise la détection de tous ces risques en une seule commande.

  • Un système Linux, macOS ou Windows
  • Accès à un terminal (bash, zsh, PowerShell)
  • curl ou wget pour télécharger le binaire (ou Homebrew sur macOS)
  • Optionnel : jq pour formater la sortie JSON

Trois méthodes sont disponibles selon votre système.

Fenêtre de terminal
# x86_64
curl -sL https://github.com/boostsecurityio/bagel/releases/latest/download/bagel_Linux_x86_64.tar.gz | tar xz
sudo mv bagel /usr/local/bin/
# ARM64
curl -sL https://github.com/boostsecurityio/bagel/releases/latest/download/bagel_Linux_arm64.tar.gz | tar xz
sudo mv bagel /usr/local/bin/
Fenêtre de terminal
brew tap boostsecurityio/tap
brew install bagel
Fenêtre de terminal
bagel version

Résultat attendu :

Version: 0.2.0
Commit: 80fcbcaae2b4d0eb1db8dd2d6b312634a8be18a5
Built At: 2026-02-12T14:02:03Z

Bagel organise son analyse en 9 sondes (probes), chacune focalisée sur un domaine du poste développeur.

Ces sondes vérifient les réglages de sécurité des outils de développement.

SondeCe qu’elle vérifieFindings typiques
gitConfiguration Git globaleSSL désactivé, credential.helper=store, protocols dangereux, fsck désactivé, hooks personnalisés
sshConfiguration SSH et clésStrictHostKeyChecking=no, ForwardAgent=yes, clés privées sans passphrase, permissions trop permissives
npmConfiguration npm/Yarnstrict-ssl=false, registres HTTP (non HTTPS), tokens dans .npmrc

Ces sondes recherchent les credentials exposées dans les fichiers du poste.

SondeCe qu’elle scanneFindings typiques
envVariables d’environnement, .bashrc, .zshrc, fichiers .envTokens API, credentials cloud en variables d’environnement
shell_history.bash_history, .zsh_historyCommandes contenant des tokens, mots de passe, clés API
cloud~/.aws/, ~/.config/gcloud/, config AzureAccess keys AWS, clés API GCP, storage keys Azure
jetbrainsFichiers de configuration des IDE JetBrainsSecrets dans les configurations de run/debug
ai_cliFichiers d’outils IA CLI (Gemini, Codex, Claude, OpenCode)Clés API OpenAI, Anthropic, Hugging Face
SondeCe qu’elle vérifieFindings typiques
ghGitHub CLI (gh)Sessions authentifiées actives, tokens d’accès

Les détecteurs sont des patterns réutilisables que les sondes utilisent pour identifier les types de secrets. Chaque détecteur reconnaît des formats spécifiques.

DétecteurSecrets détectésExemples de patterns
github-tokenTokens GitHub (6 types)ghp_ (Classic PAT), github_pat_ (Fine-grained), gho_, ghu_, ghs_, ghr_
npm-tokenTokens npmnpm_*
ai-serviceClés API de services IAsk- (OpenAI), sk-ant- (Anthropic), hf_ (Hugging Face)
http-authCredentials HTTPBearer tokens, Basic Auth, X-API-Key, http://user:pass@host
ssh-private-keyClés privées SSHRSA, DSA, EC, OPENSSH, PKCS8 — détecte chiffré vs non chiffré
cloud-credentialsCredentials cloudAKIA* (AWS), AIza* (GCP), Azure Storage Key
generic-api-keySecrets génériquesChaînes à haute entropie (analyse entropie de Shannon)
jwtJSON Web TokensPréfixe eyJ avec structure JWT standard

Passons à la pratique. Lançons un premier scan et analysons les résultats.

Le format table donne un aperçu lisible directement dans le terminal :

Fenêtre de terminal
bagel scan -f table

Résultat typique (données anonymisées) :

┌──────────────┬─────────────────────┐
│ PROPERTY │ VALUE │
├──────────────┼─────────────────────┤
│ Hostname │ dev-laptop │
│ OS │ linux │
│ Architecture │ amd64 │
│ User │ dev │
│ Scan Time │ 2026-03-06 10:57:02 │
│ Duration │ 4.832s │
└──────────────┴─────────────────────┘
Findings: 30
┌────┬──────────┬───────────────┬─────────────────────────────────────────────┐
│ # │ SEVERITY │ PROBE │ TITLE │
├────┼──────────┼───────────────┼─────────────────────────────────────────────┤
│ 1 │ critical │ cloud │ Cloud Credential Detected (AWS Access Key) │
│ 2 │ critical │ ssh │ Unencrypted SSH Private Key (OPENSSH) │
│ 3 │ critical │ env │ AI Service API Key Detected (OpenAI) │
│ 4 │ critical │ shell_history │ GitHub Token Detected (Classic PAT) │
│ 5 │ high │ env │ Generic API Key Detected (entropy: 4.90) │
│ 6 │ high │ shell_history │ Generic API Key Detected (entropy: 5.12) │
│ ...│ ... │ ... │ ... │
└────┴──────────┴───────────────┴─────────────────────────────────────────────┘

Ce scan — qui a duré moins de 5 secondes — a trouvé 30 findings dont 7 critiques. Les sondes shell_history et env sont celles qui remontent le plus de résultats, ce qui est typique d’un poste de développement actif.

Le format JSON est plus adapté à l’analyse programmatique et à l’intégration CI :

Fenêtre de terminal
bagel scan -o rapport-bagel.json

Le fichier JSON contient trois sections principales :

{
"metadata": {
"version": "0.1.0",
"timestamp": "2026-03-06T10:57:02Z",
"duration": "4.832s"
},
"host": {
"hostname": "dev-laptop",
"os": "linux",
"arch": "amd64",
"username": "dev",
"system": {
"os_version": "Ubuntu 24.04 LTS",
"kernel_version": "6.8.0-100-generic",
"cpu_cores": 16,
"ram_total_gb": 32
}
},
"findings": [
{
"id": "ssh-private-key-openssh",
"probe": "ssh",
"severity": "critical",
"title": "Unencrypted SSH Private Key Detected (OPENSSH)",
"message": "An unencrypted OPENSSH SSH private key was detected...",
"path": "file:/home/dev/.ssh/id_ed25519",
"metadata": {
"detector_name": "ssh-private-key",
"token_type": "openssh-private-key"
}
}
]
}

Pour extraire rapidement un résumé par sévérité :

Fenêtre de terminal
cat rapport-bagel.json | jq '[.findings[] | .severity] | group_by(.) | map({severity: .[0], count: length})'

Résultat :

[
{ "severity": "critical", "count": 7 },
{ "severity": "high", "count": 23 }
]

Pour lister uniquement les findings critiques :

Fenêtre de terminal
cat rapport-bagel.json | jq '.findings[] | select(.severity == "critical") | {id, probe, title}'

Pour compter les findings par sonde :

Fenêtre de terminal
cat rapport-bagel.json | jq '[.findings[] | .probe] | group_by(.) | map({probe: .[0], count: length})'

Tous les findings ne se valent pas. Voici comment les prioriser.

Les findings critical indiquent des risques d’exploitation immédiate :

FindingRisque réelUrgence
ssh-private-key-openssh (non chiffré)Si le poste est compromis, l’attaquant accède à tous les serveursImmédiat — ajouter une passphrase
cloud-credential-aws-access-key-idAccès complet au compte AWSImmédiat — rotation de la clé + utilisation d’un profil SSO
ai-service-openai-api-keyConsommation frauduleuse de l’API + fuite de donnéesImmédiat — rotation de la clé
github-token-classic-patAccès aux repos privés, push de code malveillantImmédiat — révoquer et recréer en fine-grained
http-auth-basic-auth-urlCredentials en clair dans l’historique shellRapide — nettoyer l’historique

Les findings high indiquent des expositions qui nécessitent un accès préalable pour être exploitées :

FindingRisqueAction
generic-api-key (haute entropie)Possible faux positif, mais les vrais tokens sont mélangésVérifier chaque occurrence manuellement
Tokens dans les fichiers .envExfiltration si le fichier est commité ou lu par un processus malveillantUtiliser un gestionnaire de secrets

Voici les actions concrètes pour les findings les plus courants.

Le finding ssh-private-key-openssh signale une clé privée non chiffrée. Ajoutez une passphrase sans recréer la clé :

Fenêtre de terminal
# Ajouter une passphrase à une clé existante
ssh-keygen -p -f ~/.ssh/id_ed25519

Pour les nouvelles clés, utilisez toujours Ed25519 avec passphrase :

Fenêtre de terminal
ssh-keygen -t ed25519 -C "dev@company.com"

Le finding cloud-credential-aws-access-key-id signale des access keys AWS dans ~/.aws/credentials. Migrez vers AWS SSO (IAM Identity Center) :

Fenêtre de terminal
# Configurer AWS SSO (remplace les access keys statiques)
aws configure sso

Si vous devez conserver des access keys, chiffrez le fichier credentials et assurez-vous que la rotation automatique est en place.

Les findings shell_history signalent des secrets tapés dans le terminal. Nettoyez l’historique et évitez que ça se reproduise :

Fenêtre de terminal
# Supprimer les lignes contenant des tokens de l'historique
grep -n "ghp_\|sk-\|AKIA\|Bearer " ~/.zsh_history | head -20
# Nettoyer l'historique zsh (sauvegarde d'abord)
cp ~/.zsh_history ~/.zsh_history.bak
sed -i '/ghp_\|sk-\|AKIA/d' ~/.zsh_history

Pour éviter que les secrets finissent dans l’historique :

Fenêtre de terminal
# Ajouter dans ~/.zshrc — les commandes précédées d'un espace ne sont pas historisées
setopt HIST_IGNORE_SPACE
# Utilisation : un espace avant la commande
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx

Le finding git-ssl-verify-disabled signale que la vérification SSL est désactivée. Corrigez-le :

Fenêtre de terminal
git config --global http.sslVerify true
# Si vous avez un proxy d'entreprise avec certificat auto-signé :
git config --global http.sslCAInfo /chemin/vers/ca-bundle.crt

Le finding git-credential-plaintext signale que Git stocke les mots de passe en clair dans ~/.git-credentials. Utilisez un helper sécurisé :

Fenêtre de terminal
# Linux — utiliser libsecret (GNOME Keyring)
git config --global credential.helper libsecret
# Linux — ou utiliser un cache temporaire (1h)
git config --global credential.helper 'cache --timeout=3600'
# macOS — utiliser le trousseau
git config --global credential.helper osxkeychain

Bagel utilise un fichier YAML pour personnaliser le scan. Il cherche bagel.yaml dans cet ordre :

  1. Chemin spécifié avec --config
  2. Répertoire courant (./bagel.yaml)
  3. Répertoire de configuration système (~/.config/bagel/bagel.yaml)

Si une sonde génère trop de faux positifs ou n’est pas pertinente pour votre environnement :

~/.config/bagel/bagel.yaml
version: 1
probes:
shell_history:
enabled: false # Trop de faux positifs generic-api-key dans l'historique
jetbrains:
enabled: false # Pas d'IDE JetBrains sur ce poste

Pour éviter les faux positifs sur des variables connues :

version: 1
privacy:
exclude_env_prefixes:
- "LESS"
- "LS_COLORS"
- "TERM"

La configuration par défaut active toutes les sondes. Si vous avez modifié la config et voulez revenir au scan complet :

version: 1
probes:
git:
enabled: true
ssh:
enabled: true
npm:
enabled: true
env:
enabled: true
shell_history:
enabled: true
cloud:
enabled: true
jetbrains:
enabled: true
gh:
enabled: true
ai_cli:
enabled: true
Fenêtre de terminal
# Scan avec sortie table (lisible)
bagel scan -f table
# Sauvegarder le rapport
bagel scan -o rapport.json
# Mode CI (échoue si findings)
bagel scan --strict
# Forcer la reconstruction de l'index fichier
bagel scan --no-cache
# Mode debug
bagel scan --verbose --no-progress
# Combiner les options
bagel scan --strict --no-progress -f json -o rapport.json
SymptômeCause probableSolution
bagel: command not foundBinaire pas dans le PATHVérifier : ls /usr/local/bin/bagel ou ajouter le chemin au PATH
Scan très lent (> 30s)Nombreux fichiers dans le homeUtiliser --no-progress pour voir les logs, vérifier qu’un dossier volumineux n’est pas scanné
Trop de generic-api-keyFaux positifs sur des hashes/UUIDsDésactiver shell_history dans la config ou filtrer avec jq
finding_count: 0Aucune configuration risquée détectéeVérifier que les fichiers ciblés existent (~/.gitconfig, ~/.ssh/)
Erreur permission deniedFichiers inaccessibles en lectureBagel ne scanne que les fichiers lisibles par l’utilisateur courant — c’est normal
Le cache n’est pas utiliséFichiers modifiés depuis le dernier scanComportement attendu — Bagel détecte les modifications et reconstruit l’index
exit code 2 en CIMode --strict + findings détectésComportement attendu — corriger les findings ou ajuster la configuration
  • Bagel scanne votre poste développeur en lecture seule pour identifier les configurations risquées (Git, SSH, npm) et les métadonnées de secrets — sans jamais collecter les valeurs réelles.

  • 9 sondes couvrent l’essentiel de l’environnement développeur : Git, SSH, npm, variables d’environnement, historique shell, credentials cloud, JetBrains, GitHub CLI et outils IA.

  • 8 détecteurs identifient les types de secrets par pattern (GitHub tokens, AWS keys, OpenAI keys, JWT) et par analyse d’entropie pour les secrets génériques.

  • Les findings les plus critiques sont les clés SSH sans passphrase, les credentials cloud en clair et les tokens dans l’historique shell — corrigez-les en priorité.

  • Le mode --strict (exit code 2) permet d’intégrer Bagel dans un pipeline CI pour vérifier la posture des runners ou des images de développement.

  • La configuration YAML permet de désactiver les sondes non pertinentes et d’exclure les faux positifs, pour un rapport ciblé et actionnable.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn