From 8ab0f5de9f6c5787453937f6cc3e9730bd9d43b5 Mon Sep 17 00:00:00 2001 From: bolbol Date: Mon, 24 Aug 2026 22:55:02 +0000 Subject: [PATCH] security: runbook cles API en dur + rotation BIFROST_API_KEY dsh-vps --- .../dsh-vps-secrets-en-dur-incident.md | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 hermes-nyora/dsh-vps-secrets-en-dur-incident.md diff --git a/hermes-nyora/dsh-vps-secrets-en-dur-incident.md b/hermes-nyora/dsh-vps-secrets-en-dur-incident.md new file mode 100644 index 0000000..8ddadc8 --- /dev/null +++ b/hermes-nyora/dsh-vps-secrets-en-dur-incident.md @@ -0,0 +1,54 @@ +# 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.