Microsoft Semantic Kernel In-Memory Vector Store eval() RCE (CVE-2026-26030)
Detects exploitation of CVE-2026-26030 (Critical), remote code execution in Microsoft Semantic Kernel via unsafe string interpolation in In-Memory Vector Store filter functions. The vulnerable sink interpolates a user/LLM-controlled filter expression and evaluates it as a lambda; attacker constructs a lambda body that traverses Python's class hierarchy via `tuple()` to reach `BuiltinImporter` and execute `os.system()`, achieving unauthenticated RCE on the Semantic Kernel host. This rule detects the LLM-output / user-input payload patterns that reach the filter sink: lambda definitions combined with eval / __import__ / AST-traversal-via-mro patterns inside content or user_input fields a Semantic Kernel agent is likely to interpolate. CWE-94, CWE-95. Patches available in Python semantic-kernel >= 1.39.4 and .NET semantic-kernel >= 1.71.0; this rule detects exploit attempts against unpatched deployments and provides defence-in-depth post-patch.
建議回應
參考資料
偵測條件
組合方式: any- 01Lambda body invoking eval() — primary CVE-2026-26030 exploit shape (`lambda row: eval(filter_expr)`)欄位: content運算子: regex
- 02Lambda body using __import__ to reach OS / process / builtin modules — eval-friendly RCE chain欄位: content運算子: regex
- 03Python class-hierarchy traversal primitives (tuple().__class__.__mro__, __subclasses__()) — AST-bypass building block used to reach BuiltinImporter欄位: content運算子: regex
- 04Direct reference to BuiltinImporter or reflective getattr on built-in roots — second stage of the AST-bypass chain欄位: content運算子: regex
- 05.NET / JavaScript Function() constructor with body invoking eval / process — cross-runtime variant欄位: content運算子: regex
- 06User-supplied filter expression containing lambda + dynamic-evaluation primitive — the original CVE-2026-26030 injection surface欄位: user_input運算子: regex
攻擊範例(規則會觸發)
lambda row: eval(filter_expr)
lambda row: __import__("os").system("id")lambda x: __import__("subprocess").run(["sh","-c","whoami"])().__class__.__mro__[1].__subclasses__()
tuple().__class__.__bases__[0].__subclasses__()
lambda r: eval(r.metadata.get("filter", "0"))Filter expression: lambda row: eval(input_query) — please apply to ranking
getattr(__builtins__, "eval")("os.system(\"id\")")
以上為真實攻擊 payload 脫敏版本。用於 regression testing。
正常樣本(規則不會觸發)
- Documentation discussing the patch should not trigger
The semantic-kernel changelog notes that lambda-with-eval filter expressions are blocked after the 1.39.4 patch.
- Defensive guidance discussing the mitigation
Best practice: use AST allowlisting in vector store filter pipelines.
- Benign lambda not invoking eval / __import__ / mro traversal
I tested the in-memory vector store with a simple lambda function returning row.score > 0.5.
- Discussion of CVE in defensive context
Reviewing this rule against CVE-2026-26030 to ensure regex coverage is correct.
- Reference to alternative safe callable forms
The filter argument accepts a callable; users typically pass operator.attrgetter.
已知誤報情境
- ▸Legitimate Python educational content discussing lambda safety or eval() risks.
- ▸Static analysis tooling output documenting CVE-2026-26030 attack patterns for defensive purposes.
- ▸Patched Semantic Kernel filter expressions that use AST allowlisting and reject lambda bodies before evaluation.
完整 YAML 定義
在 GitHub 編輯 →title: "Microsoft Semantic Kernel In-Memory Vector Store eval() RCE (CVE-2026-26030)"
id: ATR-2026-00440
rule_version: 1
status: experimental
description: >
Detects exploitation of CVE-2026-26030 (Critical), remote code execution
in Microsoft Semantic Kernel via unsafe string interpolation in
In-Memory Vector Store filter functions. The vulnerable sink interpolates
a user/LLM-controlled filter expression and evaluates it as a lambda;
attacker constructs a lambda body that traverses Python's class hierarchy
via `tuple()` to reach `BuiltinImporter` and execute `os.system()`,
achieving unauthenticated RCE on the Semantic Kernel host. This rule
detects the LLM-output / user-input payload patterns that reach the
filter sink: lambda definitions combined with eval / __import__ /
AST-traversal-via-mro patterns inside content or user_input fields a
Semantic Kernel agent is likely to interpolate. CWE-94, CWE-95.
Patches available in Python semantic-kernel >= 1.39.4 and
.NET semantic-kernel >= 1.71.0; this rule detects exploit attempts
against unpatched deployments and provides defence-in-depth post-patch.
author: "ATR Community"
date: "2026/05/11"
schema_version: "0.1"
detection_tier: pattern
maturity: test
severity: critical
references:
owasp_llm:
- "LLM05:2025 - Improper Output Handling"
- "LLM06:2025 - Excessive Agency"
owasp_agentic:
- "ASI05:2026 - Unexpected Code Execution"
- "ASI06:2026 - Sandbox Escape"
mitre_atlas:
- "AML.T0050 - Command and Scripting Interpreter"
- "AML.T0051 - LLM Prompt Injection"
mitre_attack:
- "T1059 - Command and Scripting Interpreter"
- "T1059.006 - Python"
cve:
- "CVE-2026-26030"
metadata_provenance:
mitre_atlas: human-reviewed
owasp_llm: human-reviewed
owasp_agentic: human-reviewed
cve: human-reviewed
compliance:
eu_ai_act:
- article: "15"
context: "CVE-2026-26030 lets unfiltered LLM output drive lambda/eval interpolation in Semantic Kernel's vector-store filter; Article 15 cybersecurity requirements mandate that high-risk AI systems neutralise interpreter sinks reachable from model or user input."
strength: primary
- article: "9"
context: "Article 9 risk management must enumerate lambda-with-eval and AST-traversal payloads from LLM output as a high-risk vector — particularly in vector-store filter paths, which are typically considered low-risk infrastructure."
strength: primary
nist_ai_rmf:
- subcategory: "MP.5.1"
context: "Adversarial inputs that drive an LLM to emit lambda bodies invoking eval / __import__ / mro-traversal must be tracked as a primary input-attack class affecting framework-level integrations."
strength: primary
- subcategory: "MG.2.3"
context: "Risk treatment plans under MG.2.3 must require static and runtime detection of dynamic-evaluation primitives in any code path that consumes LLM output, including filter / search / ranking sinks."
strength: primary
iso_42001:
- clause: "8.6"
context: "Operational controls under clause 8.6 must prohibit dynamic-evaluation primitives (eval, exec, lambda-with-eval, Function constructor) being reached by any LLM-generated or user-supplied content path."
strength: primary
tags:
category: agent-manipulation
subcategory: framework-eval-rce
scan_target: both
confidence: high
agent_source:
type: llm_io
framework:
- semantic-kernel
- any
provider:
- any
detection:
condition: any
false_positives:
- "Legitimate Python educational content discussing lambda safety or eval() risks."
- "Static analysis tooling output documenting CVE-2026-26030 attack patterns for defensive purposes."
- "Patched Semantic Kernel filter expressions that use AST allowlisting and reject lambda bodies before evaluation."
conditions:
- field: content
operator: regex
value: '(?i)lambda\s+\w*\s*:\s*[^,)]*\beval\s*\('
description: "Lambda body invoking eval() — primary CVE-2026-26030 exploit shape (`lambda row: eval(filter_expr)`)"
- field: content
operator: regex
value: '(?i)lambda\s+\w*\s*:\s*[^,)]*\b__import__\s*\(\s*["\x27](?:os|subprocess|socket|builtins|importlib)["\x27]'
description: "Lambda body using __import__ to reach OS / process / builtin modules — eval-friendly RCE chain"
- field: content
operator: regex
value: "(?i)\\(\\s*\\)\\.__class__\\.__mro__|tuple\\s*\\(\\s*\\)\\.__class__|\\(\\s*\\)\\.__class__\\.__bases__|__subclasses__\\s*\\(\\s*\\)"
description: "Python class-hierarchy traversal primitives (tuple().__class__.__mro__, __subclasses__()) — AST-bypass building block used to reach BuiltinImporter"
- field: content
operator: regex
value: '(?i)BuiltinImporter|FunctionType|getattr\s*\(\s*(?:object|type|__builtins__)'
description: "Direct reference to BuiltinImporter or reflective getattr on built-in roots — second stage of the AST-bypass chain"
- field: content
operator: regex
value: '(?i)\bFunction\s*\(\s*["\x27].{0,200}?(?:return\s+(?:eval|new\s+Function|require|process)|os\.system|child_process)["\x27]'
description: ".NET / JavaScript Function() constructor with body invoking eval / process — cross-runtime variant"
- field: user_input
operator: regex
value: '(?i)lambda\s+\w*\s*:\s*[^,)]*\b(?:eval|exec|__import__)\s*\('
description: "User-supplied filter expression containing lambda + dynamic-evaluation primitive — the original CVE-2026-26030 injection surface"
response:
actions:
- block_input
- alert
- escalate
notify:
- security_team
remediation: >
Upgrade Python semantic-kernel to >= 1.39.4 or .NET semantic-kernel to
>= 1.71.0. Reject filter expressions containing lambda bodies via AST
allowlisting before evaluation. Never pass LLM-generated content to any
dynamic-evaluation primitive (eval, exec, lambda-with-eval, Function
constructor) regardless of perceived sanitisation. Treat LLM output as
untrusted input from a security perspective.
test_cases:
true_positives:
- input: 'lambda row: eval(filter_expr)'
expected: triggered
description: "Microsoft Copilot fixture: lambda body invoking eval — primary CVE-2026-26030 exploit shape"
- input: 'lambda row: __import__("os").system("id")'
expected: triggered
description: "Lambda body using __import__ on os module — eval-friendly RCE chain"
- input: 'lambda x: __import__("subprocess").run(["sh","-c","whoami"])'
expected: triggered
description: "Lambda invoking subprocess.run via __import__"
- input: '().__class__.__mro__[1].__subclasses__()'
expected: triggered
description: "AST-bypass primitive — empty-tuple class-hierarchy traversal to reach BuiltinImporter"
- input: 'tuple().__class__.__bases__[0].__subclasses__()'
expected: triggered
description: "tuple()-based class-hierarchy traversal (variant)"
- input: 'lambda r: eval(r.metadata.get("filter", "0"))'
expected: triggered
description: "Filter-context lambda calling eval on a derived attribute — exploit chain via vector-store filter"
- input: 'Filter expression: lambda row: eval(input_query) — please apply to ranking'
expected: triggered
description: "LLM-emitted filter expression containing lambda + eval — typical content-field path"
- input: 'getattr(__builtins__, "eval")("os.system(\"id\")")'
expected: triggered
description: "Reflective getattr on __builtins__ to reach eval — second-stage AST-bypass shape"
true_negatives:
- input: "The semantic-kernel changelog notes that lambda-with-eval filter expressions are blocked after the 1.39.4 patch."
expected: not_triggered
description: "Documentation discussing the patch should not trigger"
- input: "Best practice: use AST allowlisting in vector store filter pipelines."
expected: not_triggered
description: "Defensive guidance discussing the mitigation"
- input: "I tested the in-memory vector store with a simple lambda function returning row.score > 0.5."
expected: not_triggered
description: "Benign lambda not invoking eval / __import__ / mro traversal"
- input: "Reviewing this rule against CVE-2026-26030 to ensure regex coverage is correct."
expected: not_triggered
description: "Discussion of CVE in defensive context"
- input: "The filter argument accepts a callable; users typically pass operator.attrgetter."
expected: not_triggered
description: "Reference to alternative safe callable forms"