flawopen.com/AI Security/semantic-kernel-inmemory-vector-filter-cve-2026-26030
Semantic Kernel CVE-2026-26030:フィルターのコード注入
プロンプトの影響を受けるベクトルフィルターがAST検査を回避し、Python evalに到達しました。1.39.4以降へ更新してください。[1], [4]
💡 わかりやすい解説 (ELI5)
検索規則のカードを受け取った司書が、見慣れた語を確認してからカード全体を小さなプログラムとして実行するようコンピューターに頼む場面を想像してください。カードに影響を与えられる人は検査の抜け道を利用できます。CVE-2026-26030では、モデルの影響を受けたフィルターが検索からアプリケーション内のコード実行へ進む可能性がありました。[4]
主要な概念と専門用語
InMemoryVectorStore- Semantic Kernelプロセス内のベクトルストア。検索結果を返す前にレコードを絞り込めます。[4]
Filter expression- ベクトル検索結果にレコードを含めるか決める条件式。影響を受けたPython経路では文字列をPython式として解析・評価していました。[4]
Prompt injection- 信頼できないテキストがAIモデルに影響し、意図しない操作を促します。アプリケーションがモデル入力を脆弱なフィルターへ渡す場合にリスクが生じます。[4]
フレームワーク対応
- このガイドで説明する弱点の CWE 参照: CWE-94
ステップ・バイ・ステップの攻撃フロー
ソースコード比較:脆弱 vs 堅牢化
脆弱な側は製品の実ソースではなく代表例です。モデル制御の値がeval前にPython構文へ補間されます。修正版はupstream 1.39.4の検査を抜粋しています。設定されたAST許可リストにはレコード項目へのアクセス用にast.Subscriptが含まれ、危険な属性の拒否、単独名をlambda引数に限定する検査、許可された呼び出しの確認と組み合わせます。builtinsを除いてもevalはサンドボックスになりません。パッケージを更新し、この抜粋を単独のバリデーターとしてコピーしないでください。[2], [6], [4]
脆弱な実装
# 修正前の代表例:モデル制御テキストが式を変えてしまいます。
filter_text = f"lambda x: x.city == '{model_selected_city}'"
tree = ast.parse(filter_text, mode="eval")
code = compile(tree, filename="<filter>", mode="eval")
filter_fn = eval(code, {"__builtins__": {}}, {}) # nosec
堅牢化されたセキュアパッチ
def validate_filter(self, tree):
# upstream 1.39.4の主要な検査。例外メッセージは短縮しています。
# トップレベルのフィルターはlambda式である必要があります。
if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):
raise VectorStoreOperationException("Filter must be a lambda expression")
lambda_param_names = {arg.arg for arg in tree.body.args.args}
for node in ast.walk(tree):
if type(node) not in self.allowed_filter_ast_nodes:
raise VectorStoreOperationException("AST node type is not allowed")
if isinstance(node, ast.Attribute) and node.attr in self.blocked_filter_attributes:
raise VectorStoreOperationException("Dangerous attribute is not allowed")
if isinstance(node, ast.Name) and node.id not in lambda_param_names:
raise VectorStoreOperationException("Only lambda parameter names are allowed")
if isinstance(node, ast.Call):
if isinstance(node.func, ast.Name):
func_name = node.func.id
elif isinstance(node.func, ast.Attribute):
func_name = node.func.attr
else:
func_name = None
if func_name and func_name not in self.allowed_filter_functions:
raise VectorStoreOperationException("Function is not allowed")
code = compile(tree, filename="<filter>", mode="eval")
func = eval(code, {"__builtins__": {}}, {}) # nosec
エンジニアリング&システム堅牢化チェックリスト
- ✓semantic-kernelを含むPython環境をすべて特定し、コンテナー、ノートブック、worker、CIイメージの版を記録します。[4]
- ✓1.39.4以降へ更新し、ロックファイルとイメージを再生成します。[1], [3]
- ✓更新まで本番のInMemoryVectorStoreフィルターを無効化します。[1]
- ✓ベクトル検索フィルターを追加・変更するすべてのPRで、ユーザー入力、取得文書、モデル提供引数が解析後のフィルター構造を変更できないことを示すテストを追加し、未対応形式を拒否します。[4]
- ✓実行ペイロードを使わず、危険なAST属性とlambda引数以外の名前を拒否する回帰テストを加えます。[2]
- ✓モデルが選んだフィルターは、許可するフィールドと演算子を明示した型付きデータで表現します。式文字列や未知のフィールド・演算子を拒否するテストを追加します。
- ✓エージェントのファイル、ネットワーク、資格情報への権限を最小化します。[4]
- ✓エージェントホストの検知回帰テストを追加し、子プロセスと外部接続の代表的なイベントを生成して、導入済みのテレメトリールールが両方に警告することを確認します。[4]