Seulement ce qui est sur la liste
Une liste autorisée dit exactement quelles commandes et quels chemins un agent peut utiliser. Tout ce qui n’y figure pas est refusé.
C’est utile, car un agent qui lance des commandes peut lancer la mauvaise. Une liste de ce qui est permis reste courte et se vérifie. Une liste de ce qui est interdit n’est jamais finie.
À la fin de cette leçon
Remarque
Je peux dire exactement quelles commandes et quels chemins un agent peut utiliser.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Liste autorisée | une liste de ce qui est permis, et rien d’autre | |
| Politique | les règles écrites pour un agent | |
| Argument | un mot donné à une commande | src/app.js |
| Option | un argument qui commence par un tiret | -l |
| Refus | une réponse qui dit non et donne la raison |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une politique dit ce qui est permis
Pour chaque commande, la politique liste les chemins et les options permis. Une demande a une commande et des arguments.
Vérifiez dans l’ordre. La commande est-elle sur la liste ? Chaque option est-elle sur sa liste ? Chaque chemin commence-t-il par un dossier permis ? Le premier échec donne la réponse.
Exemple détaillé : cinq demandes
| Demande | Réponse | Pourquoi |
|---|---|---|
| ls -l src/ | Autorisée | La commande, l’option et le chemin sont listés |
| rm -rf src/ | Refusée | rm n’est pas sur la liste |
| cat /etc/passwd | Refusée | Le chemin ne commence par aucun des dossiers |
| grep -r src/app.js | Refusée | L’option -r n’est pas listée pour grep |
| cat src/notes.txt | Autorisée | Le chemin commence par src/ |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur courante
Attention
Beaucoup pensent qu’un chemin qui commence par src/ est sûr. Ce n’est pas vrai. Le chemin src/../.env commence par src/ et pointe hors du dossier. Un test de préfixe n’est qu’un premier pas. La leçon 2 vérifie où va vraiment un chemin.
Un refus dit pourquoi
Un refus qui dit seulement non laisse l’agent deviner. Il peut réessayer avec une idée pire.
Dites quelle partie a échoué : la commande, l’option ou le chemin. L’agent peut alors essayer une commande permise, et une personne qui lit le journal voit ce qui a mal tourné.
Écrire l’assistant du modèle, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Les jetons d’une réponse, ou null si elle n’en donne pas.' 'function compter(donnees, nom) {' ' return donnees.usage && typeof donnees.usage[nom] === \"number\" ? donnees.usage[nom] : null;' '}' > model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire l’assistant du modèle, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function demander(messages, echantillon, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"statut \" + res.status);' ' const d = await res.json();' ' return { texte: d.choices[0].message.content, entree: compter(d, \"prompt_tokens\"), sortie: compter(d, \"completion_tokens\"), enregistre: false };' ' } catch (erreur) {' ' console.log(\"Échantillon enregistré : aucun modèle n’a répondu (\" + erreur.message + \").\");' ' return { texte: echantillon, entree: null, sortie: null, enregistre: true };' ' }' '}' 'module.exports = { demander };' >> model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire la liste autorisée, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const politique = {' ' ls: { chemins: [\"src/\", \"docs/\"], options: [\"-l\"] },' ' cat: { chemins: [\"src/\", \"docs/\"], options: [] },' ' grep: { chemins: [\"src/\"], options: [\"-n\", \"-i\"] },' '};' > autorise.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire la liste autorisée, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function decider(demande) {' ' const regle = politique[demande.commande];' ' if (regle === undefined) return \"refuse : commande absente de la liste\";' ' for (const a of demande.arguments) {' ' if (a.startsWith(\"-\")) {' ' if (regle.options.indexOf(a) < 0) return \"refuse : option \" + a + \" interdite\";' ' } else if (regle.chemins.some(function (p) { return a.startsWith(p); }) === false) {' ' return \"refuse : chemin \" + a + \" interdit\";' ' }' ' }' ' return \"autorise\";' '}' >> autorise.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire la liste autorisée, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const demandes = [' ' { commande: \"ls\", arguments: [\"-l\", \"src/\"] },' ' { commande: \"rm\", arguments: [\"-rf\", \"src/\"] },' ' { commande: \"cat\", arguments: [\"/etc/passwd\"] },' ' { commande: \"grep\", arguments: [\"-r\", \"src/app.js\"] },' ' { commande: \"cat\", arguments: [\"src/../.env\"] },' '];' 'async function main() {' ' demandes.forEach(function (d) { console.log(d.commande + \" \" + d.arguments.join(\" \") + \" -> \" + decider(d)); });' ' const q = \"En une courte phrase, pourquoi une liste de commandes autorisées est-elle plus sûre qu’une liste de commandes interdites ?\";' ' const echantillon = \"On ne peut pas prévoir toutes les mauvaises commandes, mais on peut lister les quelques bonnes.\";' ' const r = await demander([{ role: \"user\", content: q }], echantillon, 60);' ' console.log(\"le modèle dit : \" + r.texte);' '}' 'main();' >> autorise.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer la liste autorisée
docker exec -w /home/node/project agent node autorise.jsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Ce que le Run affiche
| Ligne | Ce qu’elle montre |
|---|---|
| ls -l src/ -> autorise | La commande, l’option et le chemin sont listés |
| rm -rf src/ -> refuse : commande absente de la liste | Le premier test a échoué |
| cat /etc/passwd -> refuse : chemin ... | Le chemin est hors des dossiers |
| grep -r src/app.js -> refuse : option -r interdite | L’option n’est pas listée |
| cat src/../.env -> autorise | La faille : un test de préfixe est trompé |
| le modèle dit : ... | Une phrase. Les mots changent à chaque exécution |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.