Files
chlova/docs/security.md
T
Kantin-Petit e97c885ebf feat: exposition Traefik + provisioning auth (v0.21.0)
Backend exposé via Traefik+TLS (réseau traefik-public externe, labels,
CHLOVA_DOMAIN) — surface unique. Script provision-auth (hash scrypt +
TOTP otpauth + JWT). .env.example section API/UI. security.md : surface
exposée Phase 4. Compose revalidé.

Palier de risque : privilégié (exposition réseau) — non déployé ; auth
requise pour activer l'API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 02:15:17 +02:00

4.3 KiB

Sécurité CHLOVA

Non négociable. Risque n°1 : la prompt injection. L'agent a un accès quasi-root via Portainer — le modèle de menace part du principe qu'une entrée hostile peut détourner l'agent.

Modèle de menace

  • Prompt injection : une donnée lue (message, contenu de workflow, log) tente de faire exécuter à l'agent une action non voulue.
  • Exfiltration de secrets : l'agent ne doit jamais voir de secret en clair.
  • Escalade : reclasser un asset privilégié en réversible pour contourner la review. Interdit par construction (voir risk-tiers.md).
  • Exposition réseau : une brique interne deviendrait joignable de l'extérieur.

Défenses (par couche)

1. Réduction de la surface

  • Seul le backend CHLOVA est exposé (auth + TLS). Ollama, n8n, Portainer et les serveurs MCP n'écoutent que sur chlova-internal. Voir infra/networks.md.
  • Phase 1 : surface Telegram en long-pollingaucun port publié.

2. Accès Docker via socket-proxy (obligatoire)

  • Jamais de /var/run/docker.sock monté dans l'agent ou le MCP Portainer.
  • tecnativa/docker-socket-proxy filtre les endpoints Docker autorisés.
  • Phase 1 (lecture seule) : n'autoriser que les endpoints de lecture (CONTAINERS=1, IMAGES=1, NETWORKS=1, VOLUMES=1, INFO=1, VERSION=1) et interdire tout le reste (POST=0, EXEC=0, CONTAINERS_CREATE absent…). Détail dans infra/socket-proxy/README.md.

3. Scoping des tokens

  • Token n8n : portée minimale (lecture en P1).
  • Token Portainer : portée minimale + PORTAINER_READ_ONLY=true en P1 (le serveur MCP annote readOnlyHint et réécrit les secrets en [REDACTED] avant qu'ils n'atteignent le modèle).
  • Un token = un usage. Rotation documentée.

4. Egress filtré

  • Sortie réseau par défaut refusée pour les conteneurs de l'agent.
  • Seule exception : ollama.com (proxy cloud Ollama). À appliquer au niveau pare-feu hôte / réseau Docker. Voir infra/networks.md.

5. Secrets par référence

  • Tous les secrets (dont OLLAMA_API_KEY) via variables d'env / coffre, jamais en dur. .env n'est jamais commité (.env.example fait foi des clés requises).
  • L'agent manipule des références, pas des valeurs. config.ts plante au boot (fail-closed) si un secret requis manque.

6. Lecture seule renforcée (Phase 1)

  • Le readonly-filter de l'orchestrateur n'expose au LLM que les outils MCP readOnlyHint=true. Les outils mutants ne sont pas branchés. Double barrière avec le PORTAINER_READ_ONLY=true côté serveur MCP.

7. Audit

  • Toute opération mutante est audit-loggée (qui/quoi/quand/résultat). En P1, toute exécution d'outil est tracée même si read-only.
  • Déploiements de stacks en GitOps dès que possible (rollback + audit gratuits).

Surface exposée API/UI (Phase 4)

  • Seul le backend est exposé, via Traefik + TLS (label compose, réseau traefik-public). Ollama, MCP, n8n, Portainer restent internes.
  • Login fort obligatoire : mot de passe (scrypt) + TOTP 2FAJWT court (HS256). /api/auth/login est rate-limité (anti brute-force) ; tout le reste exige un Bearer valide.
  • L'API/UI ne s'active que si l'auth est configurée (apiAuth() : 4 secrets présents). Sinon, surface Telegram seule (fail-safe).
  • Secrets d'auth via env (provision-auth les génère) ; jamais commités, masqués dans les logs (redactedConfig).
  • CORS restreint à CHLOVA_WEB_ORIGIN (dev) ; en prod le SPA est servi en same-origin par le backend (Phase 4 frontend).
  • La capacité d'écriture reste derrière le gatekeeper (Phase 2) quelle que soit la surface : l'API n'élève aucun privilège.

Invariants vérifiés par test

  • Aucun outil non-read-only n'est exposé en Phase 1 (readonly-filter.test.ts).
  • Un asset privileged ne peut pas être reclassé reversible (gatekeeper.test.ts).
  • config.ts refuse de démarrer si un secret requis manque.

Checklist de revue avant tout passage en Phase 2 (écriture)

  • socket-proxy en place, endpoints d'écriture toujours refusés tant que non requis
  • gatekeeper câblé (vérif statut avant exécution)
  • egress toujours limité à ollama.com
  • audit log couvre toute opération mutante
  • tokens re-scopés au strict besoin de la capacité ajoutée