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が2026年10月8日に公開したHighのアドバイザリ。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]
根本原因の分析 (Root Cause)
アドバイザリの対象は @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]
ソース抜粋: LangGraph.js Command判定の動作を示す縮約例。完全なソースコードではありません
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以降に更新し、ロックファイルとデプロイ成果物の解決済みバージョンを確認します。[1], [2]
- ✓リクエストJSONをgraph
.invoke()やgraph.stream()に直接渡さず、許可フィールドからサーバー側で状態を作ります。[1] - ✓制御オブジェクトを呼び出し元が制御する状態から分離し、似たフィールド名を含むJSONも通常入力となるテストを追加します。[2]
- ✓各機密ツールや副作用の実行境界で認可します。前段ノードだけに依存しません。[1]
- ✓信頼できないJSONをグラフに渡す統合テストを追加し、認証済み主体に対象リソースへの権限がない場合は機密ツールのスタブが呼び出されないことを確認します。[1], [2]