When prompts become shells: RCE vulnerabilities in AI agent frameworks
Microsoft discloses RCE vulnerabilities in Semantic Kernel AI agent framework via prompt injection.
Summary
Microsoft Security researchers discovered two critical vulnerabilities (CVE-2026-25592 and CVE-2026-26030) in Semantic Kernel, an open-source AI agent framework, that could allow attackers to achieve remote code execution through prompt injection attacks. By leveraging the framework's tool-binding mechanisms, attackers can turn prompt injections into host-level RCE, enabling unauthorized execution of system commands. The vulnerabilities underscore systemic risks in popular AI frameworks used to build production agents with active network access.
Full text
Share Link copied to clipboard! Content types Research Products and services Microsoft Defender Topics Actionable threat insightsAI and agents AI agents have fundamentally changed the threat model of AI model-based applications. By equipping these models with plugins (also called tools), your agents no longer just generate text; they now read files, search connected databases, run scripts, and perform other tasks to actively operate on your network. Because of this, vulnerabilities in the AI layer are no longer just a content issue and are an execution risk. If an attacker can control the parameters passed into these plugins via prompt injection, the agent may be driven to perform actions beyond its intended use. The AI model itself isn’t the issue as it’s behaving exactly as designed by parsing language into tool schemas. The vulnerability lies in how the framework and tools trust the parsed data. To build powerful applications, developers rely heavily on frameworks like Semantic Kernel, LangChain, and CrewAI. These frameworks act as the operating system for AI agents, abstracting away complex model orchestration. But this convenience comes with a hidden cost: because these frameworks act as a ubiquitous foundational layer, a single vulnerability in how they map AI model outputs to system tools carries systemic risk. As part of our mission to make AI systems more secure and eliminate new class of vulnerabilities, we’re launching a research series focused on identifying vulnerabilities in popular AI agent frameworks. Through responsible disclosure, we work with maintainers to ensure issues are addressed before sharing our findings with the community. In this post, we share details on the vulnerabilities we discovered in Microsoft’s Semantic Kernel, along with the steps we took to address them and interactive way to try it yourself. Stay tuned for upcoming blogs where we’ll dive into similar vulnerabilities found in frameworks beyond the Microsoft ecosystem. Background We discovered a vulnerable path in Microsoft Semantic Kernel that could turn prompt injection into host-level remote code execution (RCE). A single prompt was enough to launch calc.exe on the device running our AI agent, with no browser exploit, malicious attachment, or memory corruption bug needed. The agent simply did what it was designed to do: interpret natural language, choose a tool, and pass parameters into code. Figure 1. Illustration of CVE-2026-26030 exploitation using a local model. This scenario is the real security story behind modern AI agents. Once an AI model is wired to tools, prompt injection draws a thin line between being just a content security problem and becoming a code execution primitive. In this post in our research series on AI agent framework security, we show how two vulnerabilities in Semantic Kernel could allow attackers to cross that line, and what customers should do to assess exposure, patch affected agents, and investigate whether exploitation may already have occurred. A representative case study: Semantic Kernel Semantic Kernel is Microsoft’s open-source framework for building AI agents and integrating AI models into applications. With over 27,000 stars on GitHub, it provides essential abstractions for orchestrating AI models, managing plugins, and chaining workflows. During our security research into the Semantic Kernel framework, we identified and disclosed two critical vulnerabilities: CVE-2026-25592 and CVE-2026-26030. These flaws, which have since been fixed, could allow an attacker to achieve unauthorized code execution by leveraging injection attacks specifically targeted at agents built within the framework. In the following sections, we break down the mechanics of these vulnerabilities in detail and provide actionable guidance on how to harden your agents against similar exploitation. CVE-2026-26030: In-Memory Vector Store Exploitation of this vulnerability requires two conditions: The attacker must have a prompt injection vector, allowing influence over the agent’s inputs The targeted agent must have the Search Plugin backed by In-Memory Vector Store functionality using the default configuration When both these two conditions are met, the vulnerability enables an attacker to achieve RCE from a prompt. To demonstrate how this vulnerability could be exploited, we built a “hotel finder” agent using Semantic Kernel. First, we created an In Memory Vector collection to store the hotels’ data, then exposed a search_hotels(city=…) function to the kernel (agent) so that the AI model could invoke it through tool calling. Figure 2. Semantic Kernel agent configured with In-Memory Vector collection. When a user inputs, for example, “Find hotels in Paris,” the AI model calls the search plugin with city=”Paris”. The plugin then first runs a deterministic filter function to narrow down the dataset and computes vector similarity (embeddings). With this understanding of how a Semantic Kernel agent performs the search, let’s dive deep into the vulnerability. Issue 1: Unsafe string interpolation The default filter function that we mentioned previously is implemented as a Python lambda expression executed using eval(). In our example, The default filter will result to new_filter = “lambda x: x.city == ‘Paris’”. Figure 3. Default filtering function definition. The vulnerability is that kwargs[param.name] is AI model-controlled and not sanitized. This acts as a classic injection sink. By closing the quote (‘) and appending Python logic, an attacker could turn a simple data lookup into an executable payload: Input: ‘ or MALICIOUS_CODE or ‘ Result: lambda x: x.city == ” or MALICIOUS_CODE or ” Issue 2: Avoidable blocklist The framework developers anticipated this RCE risk and implemented a validator that parses the filter string into an Abstract Syntax Tree (AST) before execution. Figure 4. Blocklist implementation. Before running a user-provided filter code, the application runs a validation function designed to block unsafe operations. At a high level, the validation does the following: It only allows lambda expressions. It rejects outright any attempt to pass full code blocks (such as import statements or class definitions). It scans every element in the code for dangerous identifiers and attributes that could enable arbitrary code execution (for example, strings like eval, exec, open, __import__, and similar ones). If any of these identifiers appear, the code is rejected. If the code passes both checks, it is executed in a restricted environment where Python’s built-in functions (like open and print) are deliberately removed. So even if something slips through, it shouldn’t have access to dangerous capabilities. The resulting lambda is then used to filter records in the Vector Store. While this approach is solid in theory, blocklists in dynamic languages like Python are inherently fragile because the language’s flexibility allows restricted operations to be reintroduced through alternate syntax, libraries, or runtime evaluation. We found a way to bypass this blocklist implementation through a specially crafted exploit prompt. Exploit Our exploit prompt was designed to manipulate the agent into triggering a Search Plugin invocation with an input that ultimately leads to malicious code execution: A Malicious prompt demanding execution of the search_hotels function with the malicious argument. This prompt circumvented the agent to trigger the following function calling: Invocation of the “search hotels” function with the malicious argument. As result, the lambda function was formatted as the following and executed inside eval(). This payload escaped the template string, traversed Python’s class hierarchy to locate BuiltinImporter, and used it to dynamically load os and call system(). These steps bypassed the import blocklists to launch an arbitrary shell command (for example, calc.exe) while keeping the template syntax valid with a clean closing expression. The f
Indicators of Compromise
- cve — CVE-2026-25592
- cve — CVE-2026-26030