waza sécurisé

waza : sécuriser les agents et l’exécution

Anti-patterns et pièges PythonAvancé

waza : sécuriser les agents et l'exécution

Un agent IA mal configuré peut vider votre variable PATH ou lire votre fichier .ssh en une fraction de seconde. Le concept de waza sécurisé répond à cette menace d’exécution de code non fiable.

L’isolation des processus via les namespaces Linux et les cgroups est indispensable dès que vous automatisez des scripts tiers. Les fuites de secrets dans les environnements d’exécution ont augmenté de 40% dans les infrastructures cloud en 2023.

Après cette lecture, vous saurez configurer des environnements d’exécution restreints en Python pour vos agents sans compromettre votre machine hôte.

waza sécurisé

🛠️ Prérequis

Installation des outils nécessaires pour tester l’isolation :

  • Python 3.12+ (indispensable pour le typage avancé)
  • Linux Kernel 5.15+ (pour le support complet des namespaces)
  • pip install waza-tools

📚 Comprendre waza sécurisé

Le principe de waza sécurisé repose sur la stratification des privilèges. Contrairement à Docker qui utilise des couches de fichiers complexes, waza cible l’isolation des syscalls via seccomp. On utilise les namespaces Linux pour isoler le réseau (net), les utilisateurs (user) et le système de fichiers (mnt).

Comparaison technique :

| Caractéristique | Docker | waza sécurisé |
|-----------------|---------|---------------|
| Isolation | Container | Processus |
| Overhead | Élevé | Faible |
| Surface d'attaque| Large | Réduite |

L’approche waza se rapproche de la philosophie CPython : minimiser l’interface exposée. En Python, cela signifie manipuler l’objet subprocess.Popen avec une attention extrême aux descripteurs de fichiers ouverts.

🐍 Le code — waza sécurisé

Python
import os
import subprocess
from typing import List, Dict

class WazaEnvironment:
    """Gère l'exécution d'un agent dans un périmètre restreint."""
    
    def __init__(self, allowed_env_keys: List[str]):
        # On ne définit que les clés autorisées pour éviter les fuites
        self.allowed_keys = allowed_env_keys

    def execute_agent(self, command: List[str]) -> subprocess.CompletedProcess:
        # Construction d'un dictionnaire d'environnement propre
        # On interdit l'héritage direct de os.environ
        safe_env: Dict[str, str] = {}
        
        for key in self.allowed_keys:
            if key in os.environ:
                safe_env[key] = os.environ[key]
        
        # On force un PATH minimal pour empêcher l'exécution de binaires cachés
        safe_env["PATH"] = "/usr/bin:/bin"
        
        try:
            # L'exécution utilise un timeout strict pour éviter les DoS
            return subprocess.run(
                command,
                env=safe_env,
                check=True,
                text=True,
                capture_output=True,
                timeout=30
            )
        except subprocess.TimeoutExpired as e:
            print(f"L'agent a dépassé le temps imparti : {e}")
            raise
        except subprocess.CalledProcessError as e:
            print(f"Erreur d'exécution de l'agent : {e.stderr}")
            raise

📖 Explication

Dans code_source, la boucle for key in self.allowed_keys est cruciale. Elle garantit que seul le contenu explicite de allowed_keys est injecté. L’assignation manuelle de PATH évite que l’agent ne cherche des exécutables malveillants dans /tmp ou ~/.local/bin.

L’utilisation de subprocess.run avec capture_output=True permet d’isoler les flux stdout et stderr. Cela évite que l’agent ne pollue les logs de l’application principale. Le paramètre timeout=30 est votre dernière ligne de défense contre les processus zombies.

Dans code_source_2, l’usage de TypedDict avec Final permet une vérification statique via mypy. Si un développeur tente de modifier la politique à l’exécution, l’outil de typage le signalera. C’est le principe de la programmation défensive appliquée à la configuration.

Documentation officielle Python

🔄 Second exemple

Python
from typing import TypedDict, Final

class AgentPolicy(TypedDict):
    """Définition stricte des permissions de l'agent."""
    max_memory_mb: int
    allowed_networks: list[str]
    read_only_dirs: list[str]
    timeout_seconds: int

# Utilisation de Final pour garantir l'immuabilité de la configuration
DEFAULT_POLICY: Final[AgentPolicy] = {
    "max_memory_mb": 512,
    "allowed_networks": ["127.0.0.1"],
    "read_only_dirs": ["/usr", "/lib", "/bin", "/etc/ssl"],
    "timeout_seconds": 60
}

Anti-patterns et pièges

Le premier piège, et le plus fréquent, est l’utilisation de os.environ.copy(). En faisant cela, vous transférez l’intégralité de votre environnement hôte à l’agent. Si vous avez des variables AWS_SECRET_ACCESS_KEY ou DATABASE_URL chargées, l’agent y a accès. Un waza sécurisé exige une approche par liste blanche (allow-list) et non par liste noire (deny-list).

Le second piège concerne le paramètre shell=True dans subprocess.run. C’est une invitation à l’injection de commandes. Si l’agent peut manipuler une chaîne de caractères passée à la commande, il peut injecter des opérateurs comme ; rm -rf /. Utilisez toujours des listes d’arguments (['ls', '-l']) et jamais de chaînes brutes.

Le troisième piège est l’absence de limitation des ressources (cgroups). Un agent Python peut très facilement créer une boucle infinie ou allouer massivement de la mémoire, provoquant un Out-Of-Memory (OOM) killer sur l’hôte. Sans une limite RLIMIT_AS ou une gestion via cgroups, votre infrastructure est vulnérable à un déni de service interne.

Enfin, ne négligez pas le répertoire de travail (cwd). Par défaut, le processus hérite du répertoire courant. Si votre script tourne dans votre répertoire personnel, l’agent peut lire vos fichiers de configuration. Un waza sécurisé doit toujours forcer un cwd vers un répertoire temporaire et isolé, idéalement un tmpfs.

▶️ Exemple d’utilisation

Scénario : Exécution d’un script de calcul simple avec une politique restrictive.

from waza_lib import WazaEnvironment

# On n'autorise que la variable PATH
env = WazaEnvironment(allowed_env_keys=["PATH"])

try:
    # On lance une commande simple
    result = env.execute_agent(["echo", "Hello from secure agent"])
    print(f"Sortie : {result.stdout.strip()}")
except Exception as e:
    print(f"Échec : {e}")
Sortie : Hello from secure agent

🚀 Cas d’usage avancés

1. Exécution de plugins tiers : Intégrez des modules Python téléchargés dynamiquement en les exécutant via une instance de WazaEnvironment pour limiter leur accès au système de fichiers.

2. Pipeline CI/CD dynamique : Créez des environnements éphémères pour chaque test unitaire. Utilisez AgentPolicy pour définir des limites de mémoire strictes par étape de test.

3. Code Interpreter pour LLM : Lorsqu’un agent IA génère du code Python, utilisez le pattern WazaEnvironment pour exécuter ce code dans un conteneur de processus isolé, empêchant l’accès aux variables d’environnement de votre serveur d’inférence.

🐛 Erreurs courantes

⚠️ Fuite d'environnement

Copier tout l’environnement hôte vers l’agent.

✗ Mauvais

subprocess.run(cmd, env=os.environ.copy())
✓ Correct

subprocess.run(cmd, env=safe_dict)

⚠️ Injection de commande

Utiliser shell=True avec des entrées non filtrées.

✗ Mauvais

subprocess.run(f"ls {user_input}", shell=True)
✓ Correct

subprocess.run(["ls", user_input], shell=False)

⚠️ Absence de timeout

Laisser un agent tourner indéfiniment (DoS).

✗ Mauvais

subprocess.run(cmd)
✓ Correct

subprocess.run(cmd, timeout=30)

⚠️ Invisibilité du répertoire de travail

Ne pas spécifier de répertoire de travail sécurisé.

✗ Mauvais

subprocess.run(cmd)
✓ Correct

subprocess.run(cmd, cwd="/tmp/sandbox")

✅ Bonnes pratiques

Pour garantir un waza sécurisé, suivez ces règles de fer :

  • Principe du moindre privilège : Ne donnez accès qu’aux variables d’environnement strictement nécessaires.
  • Immuabilité des politiques : Utilisez Final et TypedDict pour vos configurations de sécurité.
  • Sanitisation du PATH : Redéfinissez toujours PATH de manière explicite et minimale.
  • Isolation du répertoire de travail : Utilisez toujours cwd vers un dossier dédié et nettoyé.
  • Gestion du cycle de vie : Implémenteer systématiquement des timeouts sur chaque appel de processus.
  • Audit des syscalls : Pour les environnements critiques, utilisez strace ou seccomp pour vérifier l’absence d’appels interdits.
Points clés

  • L'héritage d'os.environ est la première cause de fuite de secrets.
  • Le paramètre shell=True doit être banni de vos configurations d'agents.
  • Un waza sécurisé nécessite une définition stricte du PATH.
  • Le timeout est une protection indispensable contre les attaques DoS.
  • L'utilisation de TypedDict permet de valider les politiques au moment du développement.
  • L'isolation du répertoire de travail empêche la lecture de fichiers sensibles.
  • La limitation des ressources (cgroups) prévient l'épuisement de la mémoire hôte.
  • La sécurité doit être pensée au niveau de l'interface Python, pas seulement de l'OS.

❓ Questions fréquentes

Est-ce que waza sécurisé remplace Docker ?

Non. Docker est un outil de packaging et d’orchestration. Waza est une approche de sandboxing de processus pour l’exécution légère d’agents.

Puis-je utiliser waza avec des scripts Shell ?

Oui, mais évitez le shell=True. Passez les arguments sous forme de liste pour maintenir l’isolation.

Comment vérifier que mon environnement est réellement isolé ?

Utilisez l’outil `strace -p -e trace=file` pour vérifier que l’agent ne tente pas d’ouvrir des fichiers hors de son périmètre.

Quel est l'impact sur les performances ?

L’impact est quasi nul, car nous ne créons pas de couches de fichiers supplémentaires, contrairement à Docker.

📚 Sur le même blog

🔗 Le même sujet sur nos autres blogs

📝 Conclusion

La sécurité de l’exécution d’agents ne dépend pas de la complexité de l’outil, mais de la rigueur de sa configuration. Un waza sécurisé repose sur une gestion granulaire des variables, du chemin de recherche et du temps d’exécution. Pour approfondir la gestion des processus en Python, consultez la documentation Python officielle. Une surveillance des appels système via strace reste le seul moyen de vérifier l’intégrité d’un waza sécurisé.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *