flawopen.com/AI Security/langgraph-js-graph-input-control-directive-october-2026
GHSA-wp87-994x-j95x: JSON ошибочно принят за команду графа
LangGraph.js <1.4.21 мог принимать обычный JSON за управляющую директиву и обходить проверки или подтверждения. Обновите пакет и проверяйте состояние на сервере.[1]
Представьте граф как вокзал: багаж пассажира проверяют до посадки. В уязвимых версиях бирку со словом «Command» могли принять за разрешённый приказ переключить путь. Исправление отличает обычные объекты от Command, но приложение всё равно должно проверять права перед каждым чувствительным действием.[1], [2]
Ключевые понятия и термины
GHSA-wp87-994x-j95x- Предупреждение LangChain уровня High от 8 октября 2026 года: CVSS 4.0 — 7,6,
CWE-20; CVE не присвоен.[1] Вход графа- Объект состояния для запуска LangGraph.js; сервер должен проверить его и выбрать допустимые поля.[1]
Command- Объект LangGraph.js для изменения состояния или направления выполнения; обычный JSON остаётся данными.[2]
Граница управления- Граница, где данные приложения интерпретируются как инструкции для выбора узлов или изменения состояния.[1]
Связи со стандартами
- Ссылка CWE для слабого места, описанного в этом руководстве: CWE-20
Пошаговый сценарий атаки
Приложение принимает JSON вызывающей стороны
Уязвимая конфигурация напрямую передаёт недоверенный JSON в граф, а не создаёт проверенное состояние на сервере.[1]
Штатная обработка может быть пропущена
Объект может стать обновлением состояния или командой маршрутизации и обойти узлы проверки или подтверждения приложения.[1]
Права инструментов увеличивают последствия
Если граф предоставляет чувствительные инструменты, ввод может запустить их с правами приложения. Повторно проверяйте доступ на границе операции.[1]
Анализ первопричины
Предупреждение относится к @langchain/langgraph >=0.2.23 и <1.4.21. Приложение должно напрямую передавать недоверенный JSON в граф и полагаться на обычный путь выполнения для проверки или авторизации. В PR указано, что isCommand распознавал значение только по полю lg_name; поэтому обычный JSON-объект мог считаться Command. Граф мог применить update или goto до узлов проверки и подтверждения приложения. Предупреждение описывает возможный запуск чувствительных инструментов с правами приложения. Версия 1.4.21 отклоняет обычные объекты как Command, сохраняя настоящие экземпляры, в том числе из другой установленной копии. Это не заменяет создание состояния на сервере, список разрешённых полей и авторизацию каждой чувствительной операции. Указаны CWE-20, High, CVSS 4.0 7,6; известного CVE нет.[1], [2]
Исходный код: Уязвимый vs Защищённый вариант
Этот сокращённый пример TypeScript отражает изменение из PR #2966: одного lg_name недостаточно, чтобы обычный объект считался Command. Это не дословный исходный код и не полная реализация графа. После исправления разобранный JSON идёт по обычному пути состояния, а настоящие Command управляют графом. Форма объекта не является авторизацией. Создавайте состояние на сервере из разрешённых полей и отдельно проверяйте каждую чувствительную операцию.[2]
Фрагмент исходного кода: Сокращённая поведенческая схема распознавания Command в LangGraph.js; не полный исходный код
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";
}
Чек-лист по защите системы для инженеров
- ✓Обновите @langchain/langgraph до 1.4.21 или новее и проверьте версию в lock-файле и развёрнутом артефакте.[1], [2]
- ✓Не передавайте JSON запроса напрямую в
graph.invoke()илиgraph.stream(); формируйте состояние на сервере из явного списка допустимых полей.[1] - ✓Отделите управляющие объекты от состояния вызывающей стороны; проверьте, что JSON с похожими именами полей остаётся обычным вводом.[2]
- ✓Проверяйте права каждого чувствительного инструмента в точке операции по субъекту и ресурсу; не полагайтесь только на предыдущий узел.[1]
- ✓Добавьте интеграционный тест, который передаёт недоверенный JSON через граф и проверяет, что заглушка чувствительного инструмента не вызывается без разрешения аутентифицированного субъекта на целевой ресурс.[1], [2]