Aller au contenu

Modèle de menaces

Qui peut attaquer quoi, où sont les frontières de confiance, ce qui protège aujourd'hui et ce qui reste ouvert. Établi le 2026-10-16 par relecture du code ; chaque mesure renvoie au code qui la tient. Les décisions sous-jacentes sont dans les notes d'architecture.

Ce qu'on protège

  • La machine : Lyra peut démarrer, arrêter, cloner et détruire des VM, créer et restaurer des sauvegardes, avec des scripts lancés en root (ADR-005).
  • Les appareils du réseau local : TV, lampes, ampli, Chromecast, par les serveurs MCP.
  • Les données : texte des requêtes, historique, secrets des appareils (secrets.yaml), noms de VM et chemins de sauvegarde. Le détail est dans Flux de données.

Vue d'ensemble

flowchart LR
    subgraph USER["Compte de l'utilisateur (confiance totale)"]
        direction TB
        CLI["lyra (terminal, voix)"]
        API["lyra-control-api<br/>(neutroncore)"]
        D["lyra-daemon<br/>socket ~/.lyra/lyra.sock 0600"]
        MCP["serveurs MCP<br/>(stdio, droits de l'utilisateur)"]
        W["tâches de fond<br/>async_mcp_wrapper"]
        CLI --> D
        API --> D
        D --> MCP
        D --> W
    end
    subgraph ROOT["root"]
        S["/usr/local/lib/lyra/scripts<br/>(sudoers, une règle par script)"]
    end
    subgraph LAN["Réseau local"]
        OL["Ollama distant<br/>(HTTP, sans authentification)"]
        DEV["TV, Hue, ampli, Chromecast"]
    end
    subgraph WEB["Navigateur"]
        PAGE["page web quelconque"]
        INST["installeur --app<br/>127.0.0.1:9877"]
    end
    W -->|sudo -n| S
    MCP -->|sudo -n| S
    D -. "si llm.base_url distant" .-> OL
    MCP --> DEV
    PAGE -. "tentatives inter-origines" .-> INST

Les flèches en pointillé traversent une frontière de confiance.

Acteurs

Acteur Ce qu'il peut faire aujourd'hui
Un processus du compte de l'utilisateur Tout ce que fait Lyra : il peut parler au socket (y compris déclarer une action déjà confirmée sur la route tool), et appeler directement les scripts autorisés par sudoers avec ses propres arguments. Ce n'est pas une frontière : on considère ce compte comme de confiance.
Un autre compte de la machine Pas d'accès au socket (0600). Pouvait lire les fichiers de tâches dans /tmp et l'adresse du webhook Discord dans la liste des processus (corrigé, voir plus bas).
Une page web ouverte dans le navigateur Lyra n'ouvre aucun port. Seul l'installeur graphique écoute, pendant install.sh --app, sur 127.0.0.1:9877 (voir plus bas).
Un appareil du réseau local Peut se faire passer pour un Ollama distant (le serveur choisit l'outil et ses arguments), ou renvoyer des données trompeuses aux serveurs MCP.
Un serveur MCP malveillant ou compromis Tourne avec les droits de l'utilisateur et tout son environnement ; ses descriptions d'outils orientent la recherche ; sa sortie est lue par le modèle de dialogue.
Un texte piégé (injection de prompt) Peut arriver par la voix, le texte, ou la sortie d'un outil (nom d'application TV, contenu de fichier).

Frontières et ce qui les protège

Frontière Protection Où
Socket du démon fichier 0600, protocole typé, outils hors catalogue refusés lyra/daemon/server.py, protocol.py
Action sensible confirmation humaine ; les outils dangereux exigent un « oui » explicite, jamais automatique, même en mode performance ou avec -y lyra/core/constants.py, lyra/daemon/actions.py, tests
Automatisations sans humain (unattended) seuls les outils domestiques de PERFORMANCE_TOOLS passent ; rien ne pose de question handle_tool dans server.py
Analyse d'une phrase pour les automatisations règles seules, rien n'est exécuté lyra/daemon/analysis.py
Passage à root copie root des scripts, une règle sudoers par script, visudo -cf, aucun binaire générique ADR-005
Arguments vers les scripts listes blanches (noms, chemins, textes), jamais de shell scripts/async_mcp_wrapper.py
Secrets des appareils secrets.yaml en 0600, refus d'écrire un secret dans config.yaml installer/core/configpatch.py
Sortie d'un outil vers le modèle lue seulement par LYRA pour la réponse, tronquée à 1000 caractères ; elle ne choisit jamais l'outil suivant lyra/models/lyra_voice.py
Données gardées lyra --purge efface et vérifie lyra/utils/purge.py
Proxy d'entreprise la boucle locale est ajoutée à NO_PROXY : Ollama local, suivi et MCP ne partent pas au proxy lyra/utils/netenv.py

Risques connus

Relevés le 2026-10-16. « Proposé » signifie qu'une correction attend d'être fusionnée.

Risque État
Installeur graphique pilotable par une page web : sans contrôle d'Host, d'Origin ni de type de contenu, une page pouvait lancer l'installation, répondre aux confirmations (identifiants ask-1, ask-2…) et injecter du code dans ~/.bashrc par ollama_host. proposé (#42)
Annotation MCP destructiveHint ignorée par le démon : un outil qu'un serveur tiers déclare destructif n'avait qu'une confirmation souple, et -y l'exécutait. proposé (#41)
Fichiers des tâches de fond dans /tmp, lisibles par tous, noms prévisibles ; webhook Discord en argument de processus ; socket passé en 0600 juste après sa création. proposé (#43)
Scripts sudoers : arguments libres. Une règle autorise n'importe quels arguments ; un processus du compte peut appeler directement l'import de VM ou la restauration de sauvegarde. La sûreté dépend de la validation faite par chaque script, et le groupe libvirt donne à lui seul un pouvoir proche de root. ouvert : faire valider leurs arguments par les scripts (dépôt fedora-agents)
Ollama distant en HTTP clair, sans authentification : le texte des requêtes traverse le réseau ; un faux serveur choisit l'outil et ses arguments (les outils dangereux restent soumis au « oui »). ouvert : joindre Ollama par un tunnel (SSH, WireGuard) ou un proxy HTTPS ; llm.base_url accepte une URL https:// complète
Serveurs MCP : tout l'environnement de l'utilisateur, dépôts clonés à la dernière version sans épinglage ni vérification de signature, scripts npm install exécutés. ouvert : épingler les versions dans le catalogue
Webhook Discord lu seulement dans config.yaml alors que la documentation l'annonce dans secrets.yaml (les secrets finissaient dans le fichier non protégé, ou les notifications ne partaient pas). proposé (#43)
Injection de prompt résiduelle : la sortie d'un outil peut faire dire à LYRA un texte trompeur (par exemple une fausse consigne) ; les descriptions d'outils d'un serveur orientent le choix d'EPHAISTOS. atténué (la sortie ne pilote jamais l'outil suivant ; les actions sensibles restent confirmées)
Installation locale d'Ollama par le script officiel, téléchargé depuis ollama.com et exécuté par le shell. assumé (méthode officielle ; bundle hors ligne possible, voir Derrière un proxy, sans Internet)
Route tool : le client peut déclarer une action déjà confirmée. assumé (le socket n'est ouvert qu'au compte de l'utilisateur ; neutroncore vérifie sa propre confirmation avant d'appeler)
secrets.yaml réglé en 0600 juste après son écriture ; ses copies .bak-* restent sur le disque. ouvert, faible

Hors périmètre

  • Un attaquant root, ou qui exécute déjà du code sous le compte de l'utilisateur : il a de toute façon les droits que Lyra utilise.
  • La sécurité propre des appareils pilotés (TV, pont Hue, ampli) et de leurs protocoles.
  • lyra-control-api et neutroncore, qui ont leur propre authentification (clé, jeton de confirmation).