Aller au contenu
Planifier puis exécuter : un patron de sécurité et ce qu'il interditLecture : 0 %

Planifier puis exécuter : un patron de sécurité et ce qu'il interdit

Ce que garantit un plan figé avant toute lecture de contenu non fiable, ce qu'il ne garantit pas sur les arguments, et les fonctionnalités auxquelles il faut renoncer pour en bénéficier.

Par Elias Varen7 min de lectureMembres

Dans une boucle d'agent ordinaire, le modèle choisit sa prochaine action après avoir lu le résultat de la précédente. C'est ce qui le rend utile, et c'est aussi la faille, car si le résultat contient un texte écrit par un attaquant, ce texte participe au choix de l'action suivante. Le contenu non fiable tient le volant.

Le patron « planifier puis exécuter » retire le volant. Le modèle établit la liste complète des actions à partir de la seule demande de l'utilisateur, avant d'avoir lu quoi que ce soit d'extérieur, puis un exécutant déroule le plan. Les résultats d'outils circulent comme des données d'une étape à l'autre, sans jamais ajouter, retirer ni réordonner une étape.

Parmi les défenses contre l'injection, celle-ci est l'une des rares à donner une garantie structurelle au lieu d'une probabilité. Elle se paie en utilité, et plus cher que les schémas ne le laissent croire.

L'intégrité du flot de contrôle

La propriété obtenue est une intégrité du flot de contrôle. La séquence des appels d'outils est décidée dans un contexte qui ne contient que du texte fiable, le prompt système et la demande de l'utilisateur. Aucune injection placée dans un document, un ticket ou une page web ne peut faire apparaître un appel qui n'était pas prévu.

Boucle réactive                      Planifier puis exécuter

demande ──► modèle ──► outil A       demande ──► planificateur ──► plan [A, B, C]
              ▲          │                                            │
              └──────────┘                        exécutant ◄─────────┘
        (le résultat de A                         A ─► B ─► C
         choisit la suite)                  (les résultats sont des valeurs,
                                             jamais des instructions)

Le plan est un objet que le code valide avant exécution, et le modèle ne se contente pas de relire un texte. Chez nous, il a cette forme :

PHP
final readonly class Etape
{
    /** @param array<string, Litteral|Reference> $arguments */
    public function __construct(
        public string $outil,
        public array $arguments,
        public string $resultat, // nom de variable, ex. "$ticket"
    ) {}
}

final readonly class Plan
{
    /** @param list<Etape> $etapes */
    public function __construct(public array $etapes) {}
}

Un argument est soit un Litteral fixé à la planification, soit une Reference vers le résultat d'une étape antérieure. L'exécutant est un programme ordinaire qui parcourt les étapes, résout les références et appelle les outils, sans contenir de modèle. Ce détail compte, parce qu'un exécutant qui « interprète » un résultat pour savoir quoi faire reconstruit la boucle réactive.

Planifier puis exécuter : un patron de sécurité et ce qu'il interdit · Deepstack