# Cles API en dur dans un repo Gitea nouvellement cree — incident et fix **Instance auteur** : hermes-nyora (detection) + Claude (remediation) **Date** : 2026-08-24 **Tags** : securite, git, secrets, dsh-vps, bifrost **Statut** : clos pour BIFROST_API_KEY, ouvert pour OPENCODE_DIRECT_API_KEY (action Nabil) --- ## Ce qui s'est passe Lors de l'initialisation du depot `bolbol/dsh-vps` (commit initial, mission bridge MCP DSH), `entrypoint.sh` a ete commite avec deux secrets reels en fallback shell : ```bash BIFROST_API_KEY: ${BIFROST_API_KEY:-sk-bf-3727af3c-c4e9-43f5-a6b1-08beb1dae9d4} OPENCODE_DIRECT_API_KEY: ${OPENCODE_DIRECT_API_KEY:-sk-DWbZ2mr6UvFnWH8P6ZhsUjc6LJXtvJSY8mdYdSOueyGSwFn6LZRjUNzuazc5nGkK} ``` Le meme fichier gerait deja `CONTEXT_HUB_API_KEY` correctement (sourcee depuis `$DSH_HOME/.env`, jamais en dur) — le pattern correct existait a cote du pattern fautif, dans le meme fichier. Aggravant : le depot avait ete cree en **visibilite publique** sur le Gitea interne (`private: false`) — decouvert en verifiant, pas suppose. --- ## Detection hermes-nyora a relu `entrypoint.sh` sur `main` avant de valider une procedure et a trouve les deux cles en clair — reflexe de verification avant action, pas une alerte automatique. --- ## Remediation appliquee 1. Repo passe en prive immediatement (`PATCH /api/v1/repos/bolbol/dsh-vps` avec `private: true`). 2. `BIFROST_API_KEY` (`vk-dsh-vps` dans `governance_virtual_keys` de Bifrost) rotee directement en base (`config.db`, backup avant modif, `value` + `value_hash` — SHA-256 du plaintext, verifie contre une cle existante avant d'ecrire). Ancienne valeur invalidee immediatement. 3. `$DSH_HOME/.env` et `.credentials.yaml` sur le conteneur dsh-vps mis a jour avec la nouvelle valeur, conteneur redemarre (`docker compose restart`, pas `up -d`), fonctionnement verifie par un vrai appel `chat/completions` reussi. 4. `entrypoint.sh` corrige (en parallele par Gemini) : `${VAR:-secret}` -> `${VAR:?variable manquante}`, echec explicite au lieu d'un defaut dangereux. `OPENCODE_DIRECT_API_KEY` reste en l'etat — c'est en realite `BIFROST_OPENCODE_KEY`, la cle maitresse OpenCode.ai partagee par tout Bifrost, pas une cle scopee comme `BIFROST_API_KEY`. Rotation hors de portee de Claude (compte SaaS externe), necessite Nabil. --- ## Piege identifie a generaliser Un fichier peut contenir a la fois le bon pattern (`.env` source, jamais en dur) et le mauvais pattern (fallback litteral) **dans le meme script** — la presence d'un exemple correct ne garantit pas que tout le fichier suit la meme discipline. Toujours grep `sk-\|API_KEY.*:-\|_KEY.*=.*[A-Za-z0-9]\{20,\}` sur tout fichier avant un premier commit dans un nouveau depot. Verifier la visibilite (`private`) d'un depot des sa creation, jamais supposer qu'un depot interne est prive par defaut. --- ## Reste a faire (Nabil) - Rotation de `BIFROST_OPENCODE_KEY` sur le dashboard OpenCode.ai, puis mise a jour dans `hermes-platform/.env` et `$DSH_HOME/.env` de dsh-vps. - Decision : garder `agent-default-model: opencode-direct/ox-alpha-free` (modele gratuit temporaire hors Bifrost, necessite la cle maitresse) ou basculer dsh-vps sur un modele Bifrost-only (`deepseek-v4-flash` via `vk-dsh-vps`, deja fonctionnel, deja scope). - L'historique git du commit initial contient toujours les deux cles en clair — residuel tant que la seconde n'est pas rotee, meme depot prive.