flawopen.com/AI Security/langgraph-js-graph-input-control-directive-october-2026
GHSA-wp87-994x-j95x : JSON pris pour un ordre du graphe
LangGraph.js <1.4.21 pouvait interpréter un JSON ordinaire comme une directive de contrôle et contourner validation ou approbation. Mettez à jour et validez l’état côté serveur.[1]
Imaginez un graphe comme une gare : les bagages doivent être contrôlés avant l’embarquement. Dans les versions concernées, une étiquette « Command » pouvait passer pour un ordre autorisé de changer de voie. Le correctif distingue les objets simples des objets Command, mais l’application doit toujours vérifier les droits avant chaque action sensible.[1], [2]
Concepts Clés et Termes
GHSA-wp87-994x-j95x- Avis High de LangChain publié le 8 octobre 2026 ; il indique CVSS 4.0 7,6,
CWE-20et aucun CVE connu.[1] Entrée du graphe- Objet d’état fourni à une exécution LangGraph.js ; le serveur doit le valider et sélectionner ses champs.[1]
Command- Objet LangGraph.js qui met à jour l’état ou dirige l’exécution ; le JSON ordinaire reste une donnée.[2]
Frontière de contrôle- Frontière où les données deviennent des instructions choisissant des nœuds ou modifiant l’état.[1]
Correspondances de référentiels
- Référence CWE pour la faiblesse décrite dans ce guide : CWE-20
Déroulement de l'Attaque Étape par Étape
L’application reçoit le JSON du client
Le déploiement concerné transmet directement au graphe un JSON non fiable au lieu de construire un état validé côté serveur.[1]
Le traitement normal peut être contourné
L’objet peut devenir une mise à jour d’état ou une instruction de routage et éviter les nœuds de validation ou d’approbation de l’application.[1]
Les droits des outils amplifient l’impact
Si le graphe expose des outils sensibles, une entrée malveillante peut, selon l’avis, les exécuter avec les droits de l’application. Réautorisez au niveau de chaque opération.[1]
Analyse de Cause Racine
L’avis concerne @langchain/langgraph >=0.2.23 et <1.4.21. L’application doit transmettre directement au graphe un JSON non fiable et compter sur son chemin normal pour valider ou autoriser. La PR indique que isCommand reconnaissait auparavant une valeur à partir du seul champ lg_name ; un objet JSON ordinaire pouvait donc être pris pour un Command. Le graphe pouvait appliquer update ou goto avant les nœuds de validation ou d’approbation de l’application. L’avis décrit un risque d’exécution non autorisée d’outils sensibles avec les droits de l’application. La version 1.4.21 rejette les objets simples comme Command tout en conservant les vraies instances, y compris celles d’une autre copie installée. Cela ne remplace ni la construction de l’état côté serveur, ni la liste des champs admis, ni l’autorisation à chaque opération sensible. L’avis attribue CWE-20, High et CVSS 4.0 7,6 ; aucun CVE n’est connu.[1], [2]
Code Source : Vulnérable vs Sécurisé
Cet exemple TypeScript réduit reprend le changement décrit dans la PR #2966 : lg_name seul ne suffit plus à faire d’un objet simple un Command. Ce n’est ni le code source exact ni un graphe complet. Après correction, le JSON analysé suit le chemin d’état ordinaire et les vrais objets Command gardent leur fonction de contrôle. La forme d’un objet ne constitue pas une autorisation. Construisez l’état côté serveur à partir d’une liste de champs admis et autorisez chaque opération sensible.[2]
Extrait source: Illustration comportementale réduite du discriminateur Command de LangGraph.js ; pas le code source complet
type CommandLike = { lg_name: string; goto?: unknown; update?: unknown };
function isCommand(value: unknown): value is CommandLike {
return typeof value === "object" && value !== null &&
"lg_name" in value && value.lg_name === "Command";
}
type CommandLike = { lg_name: string; goto?: unknown; update?: unknown };
function isPlainObject(value: object): boolean {
const prototype = Object.getPrototypeOf(value);
return prototype === Object.prototype || prototype === null;
}
function isCommand(value: unknown): value is CommandLike {
return typeof value === "object" && value !== null &&
!isPlainObject(value) &&
"lg_name" in value && value.lg_name === "Command";
}
Liste de Contrôle de Sécurité pour l'Ingénierie
- ✓Mettez @langchain/langgraph à la version 1.4.21 ou ultérieure et vérifiez la version dans le fichier de verrouillage et l’artefact déployé.[1], [2]
- ✓Ne transmettez pas le JSON d’une requête directement à
graph.invoke()ougraph.stream(); construisez l’état côté serveur à partir de champs explicitement admis.[1] - ✓Séparez les objets de contrôle de l’état fourni par l’appelant et testez qu’un JSON analysé reste une entrée ordinaire avec des noms de champs similaires.[2]
- ✓Autorisez chaque outil ou effet sensible au point d’opération selon l’identité authentifiée et la ressource ; ne comptez pas seulement sur un nœud précédent.[1]
- ✓Ajoutez un test d’intégration qui transmet un JSON non fiable au graphe et vérifie qu’un outil sensible simulé n’est jamais appelé sans autorisation du principal authentifié pour la ressource visée.[1], [2]