On 7 May 2026, Microsoft security researchers published details of two critical vulnerabilities in Semantic Kernel, Microsoft's open-source framework for building AI agents, that allowed a prompt injection to become code execution on the machine running the agent. One flaw affected the .NET SDK and the other the Python package, and both scored 9.9 on the CVSS scale. The advisories and fixed versions were published in February 2026, but the write-up is a clear demonstration that in agentic applications every tool parameter the model can influence is attacker-controlled input.
Key Facts#
- CVE-2026-25592 (.NET): Arbitrary file write through the
SessionsPythonPluginin the Semantic Kernel .NET SDK. It affectsMicrosoft.SemanticKernel.Coreversions before 1.71.0 and is fixed in 1.71.0 (GitHub advisory GHSA-2ww3-72rp-wpp4, published 6 February 2026, CWE-22). The same advisory lists the Python package before 1.39.3. - CVE-2026-26030 (Python): Remote code execution through the
InMemoryVectorStorefilter in the Pythonsemantic-kernelpackage. It affects versions before 1.39.4 and is fixed in 1.39.4 (GHSA-xjw9-4gw8-4rqx, published 19 February 2026, CWE-94). - Severity: Both advisories carry a CVSS 3.1 score of 9.9, rated critical.
- Researchers' write-up: Microsoft published the technical details on 7 May 2026 as the first post in a research series on vulnerabilities in AI agent frameworks.
- Scope: Semantic Kernel has more than 27,000 stars on GitHub, according to Microsoft.
- Workarounds: The .NET advisory recommends a function invocation filter that allowlists file paths. The Python advisory advises against using
InMemoryVectorStorein production until you upgrade.
What Happened#
Both vulnerabilities follow the same pattern. The model behaves as designed: it converts natural language into structured tool calls. The weakness is in how the framework trusts the arguments that the model produces.
The .NET flaw sat in SessionsPythonPlugin, which lets an agent run Python code inside Azure Container Apps dynamic sessions, isolated cloud sandboxes with their own file system. Helper methods move files across that boundary. According to Microsoft, DownloadFileAsync was accidentally marked with the [KernelFunction] attribute, which advertised it to the model as a callable tool. Its localFilePath parameter decides where the downloaded bytes are written on the host, and it had no path validation. Microsoft's proof of concept chained two tool calls: first, an injected prompt used the code-execution tool to create a malicious script inside the sandbox; then a second instruction told the model to download that script into the Windows Startup folder on the host, where it would run at the next sign-in. The researchers also describe the reverse problem in the upload helper, which accepted any local path and could be abused to copy files such as SSH keys into the sandbox.
The Python flaw was in the default filter used when the Search Plugin is backed by the in-memory vector store. The filter built a Python lambda expression by inserting a model-controlled value into a string and then ran it with eval(). The developers had added an abstract syntax tree blocklist, but Microsoft showed that a payload could walk Python's class hierarchy to reach the module importer and run a shell command without using any of the blocked names.
The fixes remove the root causes. In .NET, DownloadFileAsync is no longer exposed to the model, and a validation step canonicalizes paths and checks them against allowed directories, with similar opt-in protection for uploads. In Python, the filter now uses an allowlist of syntax node types and function calls, blocks attributes used for class traversal and restricts bare names to the lambda parameter.
Background#
Tool calling changed the threat model of LLM applications. A chatbot that only produces text can leak or invent information; an agent whose tools write files, query databases or run scripts can be steered into acting on the host. Microsoft's researchers frame the key lesson bluntly: the model is not a security boundary, and "any tool parameter the model can influence must be treated as attacker-controlled input."
They also compare the situation to early web security, when untrusted input flowed straight into SQL queries and file system calls. The mitigation is the same: validate at the point where input meets a dangerous operation. Microsoft says the next posts in its series will cover structurally similar vulnerabilities in widely used third-party agent frameworks. It has also published a capture-the-flag version of the vulnerable Python agent for hands-on practice, along with Microsoft Defender hunting queries that look for agent processes spawning shells.
Why It Matters for Developers#
If you run Semantic Kernel in .NET, start by confirming your version. dotnet list package --vulnerable and NuGet Audit during restore will both flag packages with known advisories. Then treat the incident as a design review for every agent you own.
- Audit what the model can call. Every method with
[KernelFunction]is part of your attack surface. The .NET bug was a helper that was never meant to be a tool. Review plugins, including built-in ones, for methods that touch the file system, processes or the network. The Semantic Kernel guide covers plugins and filters in depth. - Validate arguments where they are used. Canonicalize paths, check them against an allowlist and reject everything else. The same rule applies to tools built with Microsoft.Extensions.AI or the Microsoft Agent Framework; see the function calling guide for tool design.
- Add a filter as defense in depth. The advisory's suggested workaround is a function invocation filter. Here is a minimal version that rejects any
localFilePathargument outside an approved folder:
using Microsoft.SemanticKernel;
public sealed class LocalPathGuardFilter(string allowedRoot) : IFunctionInvocationFilter
{
private readonly string _root =
Path.TrimEndingDirectorySeparator(Path.GetFullPath(allowedRoot))
+ Path.DirectorySeparatorChar;
public async Task OnFunctionInvocationAsync(
FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
{
if (context.Arguments.TryGetValue("localFilePath", out var value)
&& value is string path
&& !Path.GetFullPath(path).StartsWith(_root, StringComparison.Ordinal))
{
throw new UnauthorizedAccessException(
$"'{context.Function.Name}' attempted to use a path outside '{_root}'.");
}
await next(context);
}
}
// Register on the kernel that runs your agent.
kernel.FunctionInvocationFilters.Add(
new LocalPathGuardFilter(Path.Combine(AppContext.BaseDirectory, "agent-files")));Upgrading remains the real fix, because a filter cannot anticipate every future tool. Finally, run agent hosts with least privilege and watch for the host-level signals Microsoft highlights, such as an agent process launching a shell or writing to startup locations. The Responsible AI and LLM security guide collects these defenses in one place.
What's Next#
Microsoft has said its research series will move beyond Semantic Kernel to similar execution flaws in other widely used agent frameworks, which suggests more advisories may follow elsewhere in the ecosystem. For .NET teams, the practical follow-up is to put AI agent packages on the same patch cadence as web frameworks, make tool review part of code review and include prompt-injection cases in security testing. Framework defaults may keep tightening, but that is a hope rather than an announced plan, so do not rely on defaults alone.