FlawOpen

flawopen.com/AI Security/langgraph-js-graph-input-control-directive-october-2026

● CWE-20 · CVSS v4 7.6[1] · Высокий
Исследования · FlawOpen

GHSA-wp87-994x-j95x: JSON ошибочно принят за команду графа

LangGraph.js <1.4.21 мог принимать обычный JSON за управляющую директиву и обходить проверки или подтверждения. Обновите пакет и проверяйте состояние на сервере.[1]

Вектор CVSSCVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N[1]
💡 Простыми словами (ELI5)

Представьте граф как вокзал: багаж пассажира проверяют до посадки. В уязвимых версиях бирку со словом «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

Пошаговый сценарий атаки

Шаг 1

Приложение принимает JSON вызывающей стороны

Уязвимая конфигурация напрямую передаёт недоверенный JSON в граф, а не создаёт проверенное состояние на сервере.[1]

Шаг 2

Данные принимаются за объект управления

До 1.4.21 одного поля lg_name было достаточно, чтобы обычный объект выглядел как Command. Ошибка находится в распознавании типа, а не в разборе JSON.[1], [2]

Шаг 3

Штатная обработка может быть пропущена

Объект может стать обновлением состояния или командой маршрутизации и обойти узлы проверки или подтверждения приложения.[1]

Шаг 4

Права инструментов увеличивают последствия

Если граф предоставляет чувствительные инструменты, ввод может запустить их с правами приложения. Повторно проверяйте доступ на границе операции.[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";
}

Чек-лист по защите системы для инженеров

Источники

← AI Security Directory →