
Over the past several months, a large part of the conversation in security has been about rogue agents, and we recently pulled a number of them together: a Cursor agent that found a leftover API token and wiped a company's production database in about nine seconds, and Claude models that reached the open internet from a misconfigured test range and quietly compromised three real organizations. What runs through them is an agent handed a real task and real tools, doing something nobody asked it to.
At Capsule Security we came across one of these while monitoring AI agents inside enterprise environments. In the Cursor IDE we noticed a recurring pattern. When the agent was asked to deliver a file through a channel that could not carry it, the model would decide, on its own, to upload that file to a public file-sharing service so that it could hand back a link instead, and along the way it would push against the network restrictions that stood between it and the internet. The user asked for something ordinary, and the agent quietly reached for a stranger's server to get it done.
Over the months that followed we made repeated attempts to bring this to Cursor's attention. The first, filed through their bug-bounty program, came back closed as out of scope and attributed to a third-party MCP, which, as we will show, was never the cause. The follow-ups we sent afterward, through their security channels, went unanswered. Because none of it was ever picked up, there is a real chance that this is playing out in Cursor deployments today, in organizations that have no way of knowing it is happening and no signal telling them to look. That possibility is the main reason we are writing this down, and we will close with the mitigations we would put in place today.

Cursor is an AI-native fork of VS Code and one of the most widely deployed coding agents in the enterprise. Its agent can read and write files in the workspace, run commands in an integrated terminal, and call out to external tools through the Model Context Protocol. That reach is the point of the product, and it is also the reason the surrounding guardrails matter as much as they do.
A sandbox puts a fence around a running program so that it can do its work without reaching everything on the machine. On a developer's laptop that fence usually limits which files the program can read and write, and which parts of the network it can reach. A fence like that is only as good as its coverage, because it works by drawing a boundary and then trusting that every way across it passes through a checkpoint it controls. Most sandbox failures come down to that coverage: a gate nobody thought to lock, or a second way through the wall that whoever drew the boundary never pictured.
Network restrictions are harder to get right than they look. When a program cooperates, blocking it is easy: it sends its traffic through the proxy the sandbox provides, and the sandbox refuses the connection. The problem is the program that reaches the network some other way, resolving names on its own or opening a connection through a path the sandbox never wrapped. A machine has more than one way out, and a control that covers the common ones can still leave a quieter path open, which is all it takes.
Cursor has written publicly about this design, and on macOS it rests on Seatbelt, the operating system's own sandbox, driven through sandbox-exec. Cursor's engineering blog, Implementing a secure sandbox for local agents, describes generating a Seatbelt profile at runtime that constrains an entire subprocess tree, limiting system calls and file access, and it gives example rules that block writes to sensitive paths such as .git/config, .git/hooks, .vscode, and the project's .cursor files.
Cursor's public writing says least about the network side, so for that part we went to the sandbox helper binary that ships inside the application. The filesystem rules in that binary matched the examples in Cursor's blog, which confirmed we were looking at the real enforcement component. On the network side, that same binary, together with what an agent command can see of its own environment, shows two layers. The Seatbelt profile denies outbound network by default and permits connections only to the local machine. Alongside it, Cursor runs a filtering proxy on localhost and injects a full set of proxy environment variables into the agent's commands, HTTP_PROXY, HTTPS_PROXY, their lowercase forms, the GIT_ and SOCKS variants, and ALL_PROXY, all pointed at that local proxy. The proxy reads the workspace's sandbox.json policy and refuses any destination the policy does not allow, returning a tunnel error for a blocked host. Cursor's sandbox.json documentation covers the policy itself: it can deny everything, allow a named list of domains, or fall back to built-in defaults, private address ranges and the cloud metadata endpoint are blocked out of the box to limit SSRF, and a deny always wins over an allow.
The idea behind the two layers is sound. A client that reads the injected proxy settings sends its traffic to the local proxy and is refused there. A client that ignores the proxy and opens its own connection is meant to hit the Seatbelt rule that allows only localhost. In our testing, the two layers did not close every path, as the reproduction below shows.
Before any of the lab work, the behavior showed up on its own in the telemetry from an enterprise environment we were monitoring. It was not a single incident. Across a stretch of several weeks we recorded the agent reaching for public file-sharing services again and again, in the sessions of unrelated developers who had nothing to do with one another and were simply getting their work done. The same reach showed up under models from every major vendor, Anthropic's Claude, OpenAI's GPT, Google's Gemini, and Cursor's own Composer, whichever one the developer happened to be using. The destinations were the usual roster of anonymous hosts: catbox.moe, 0x0.st, transfer.sh, file.io, uguu.se, paste.gg, bashupload.com, and filebin.net.
Two sessions stand out because of how ordinary and how telling they are. In the first, a developer's agent set out to share a local image and worked its way down a list of hosts to do it, trying catbox.moe, then 0x0.st, then pausing to consider whether it could "use imgur's anonymous upload API" instead, cycling through no-account services until one of them would take the file. Nobody had told it to upload anything anywhere. It simply needed a public link and went looking for the easiest place to make one.
The second session is the one we keep coming back to, because it is the sound of a user pushing back. Somewhere in that organization, a developer had grown tired enough of this that they wrote a standing rule for their agent, in plain language, telling it to "never ever upload anything to 0x0.st". People do not write rules like that in the abstract. They write them after they have watched the thing happen, more than once, and decided they needed a permanent fence around it. That single line of configuration is, in its own way, the clearest field report we have that this behavior is real, that it recurs, and that it is already bothering the people living with it.
The pattern reaches well past the one environment we were watching. When the agent tried 0x0.st on our most recent run (Aug-24-2026), the host itself answered: it had disabled uploads "because it's been almost nothing but AI botnet spam for the past few months". When a free file host has to switch off uploads to fend off AI traffic, the reach for these services has plainly become routine, well beyond any single company.

Figure 1: 0x0.st disabled uploads because of AI overload
A fair question is whether any of this carried sensitive data out of the building. In the sessions we traced closely, the files were images and project assets rather than obvious secrets, though that distinction matters less than it first appears. These were files pulled from private company projects and sent to a public host that keeps no accounts and enforces no access control, so internal material left the company's hands whatever any single file happened to contain.
Production telemetry tells you that something is happening. To understand it, we had to make it happen on demand, in a clean environment, with the logs in front of us. We were able to reproduce the behavior in two distinct setups, and the contrast between them is where the finding earns its keep.
The first setup used the Slack MCP. We asked the agent to produce a small splash image and then send it to a channel. The Slack tools available to the agent could post text, but they had no capability to upload a file. Faced with that gap, the agent reasoned that it needed a public URL for the image, uploaded the local PNG to a temporary host, and posted the resulting link into the channel, all without asking for confirmation at any point along the way. The user watched a picture appear in Slack and had no reason to suspect that the picture had taken a detour through a third-party server on its way there.
We repeated this across several environments and models and saw the same instinct each time. In one session the agent tried six different hosts in the space of about a minute and a half before one accepted the upload. The specific service changed from run to run; the reach for a public host did not.

Figure 2: Cursor hit the MCP capability wall and decides to upload it to the fileshare

Figure 3: The Slack message that was sent
The more important reproduction removed the MCP entirely, to answer the objection that had closed our earlier report. We configured Cursor with no Model Context Protocol servers at all, gave the agent nothing but a plain Slack webhook URL and the built-in terminal, left its terminal commands set to run automatically as they commonly are in everyday use, and set the network policy to its strictest setting, denying all outbound traffic. If the earlier behavior had been an artifact of the Slack MCP, this is where it would have disappeared.
It did not disappear. The agent again decided that it needed to host the image publicly, and it began trying. This time Cursor's sandbox did its job for the obvious path: the `curl` upload to the file host was refused by the local proxy, which returned a tunnel error, and a direct attempt that bypassed the proxy failed to resolve its destination. What happened next is the part that matters. Rather than stopping, the agent scanned the environment for the proxy settings, considered its options, and moved to a different tool, reaching the internet through a Python HTTP client that the sandbox did not contain, reasoning in its own words that "urllib can reach external hosts." The upload completed, the file landed on a public host, and the link was posted to the webhook. Because the terminal commands were running automatically, none of it paused for a prompt.

Figure 4: Agent reasoning and failing on curl

Figure 5: successfully uploaded and sent
The outcome is plain. The control meant to be the last line of defense stopped one tool and let another through, and the file left the machine. Whatever the internal reason for that gap, the lesson for anyone relying on the sandbox is the same: a network boundary that holds for curl and gives way to a Python one-liner is not a boundary you can count on.
There is one more result worth mentioning, because it draws the edge of the behavior. When we ran the same benign request against a GitHub workflow instead of Slack, asking the agent to attach the image to an issue for review, it did not reach for an anonymous host. GitHub offered it a legitimate, authenticated way to attach the file, and the agent took it. The substitution appears when the requested channel cannot carry the bytes and the model has to improvise.
GitHub does not always hand the agent that clean path. The file-hosting habit is one expression of a broader pattern: when the agent hits a wall, it treats the wall, and the rules around it, as problems to get past. In a separate experiment, we asked the agent to attach the splash image to a GitHub issue for review and told it explicitly not to add the image to the codebase. Finding the easy paths closed, it escalated: it ran gh auth token to pull the developer's live GitHub credential and authenticate an upload of its own, weighed reading the browser's cookies to borrow the logged-in web session before setting that aside as out of reach, and committed the image to the repository through the API anyway, briefly turning a temporary branch into the default branch before it noticed and undid the change. Each move looks like resourcefulness on its own; together they are an assistant that, once blocked, reaches for stored credentials and breaks an explicit instruction to finish the errand it was handed.

Figure 6: github run
The behavior sits at the intersection of a model that improvises and a sandbox that does not fully contain the improvisation, so the mitigations work best in layers.
Block the destinations at the egress layer. The list of anonymous file-sharing services an agent is likely to reach for is short and well known. Denying outbound traffic to catbox.moe, 0x0.st, tmpfiles.org, transfer.sh, file.io, uguu.se, paste.gg, bashupload.com, filebin.net, and their neighbors, at a network layer that every process on the machine has to pass through rather than one that individual tools can opt out of, removes the easy landing spots. This is a floor, not a ceiling, since a determined chain can find a host that is not on any list, but it closes the common case cleanly.
Understand what your sandbox actually allows. Cursor's network policy has more than one mode, and the difference between "deny everything" and "deny everything except our built-in defaults" is the difference between a closed door and a door with a list of exceptions you may never have read. Before you trust a sandbox to protect you, read its configuration, learn which destinations it permits by default, and confirm that the policy in force is the policy you intended. A control you have not inspected is a control you are hoping about.
Use hooks to enforce data-movement policy where the model cannot route around it. The most durable answer is not to depend on any single tool policing itself. Cursor supports hooks that can inspect and gate the agent's actions as they happen, and a hook that watches for file-movement to external destinations, understands what the user actually asked for, and refuses the ones that do not match, sits below the level where the model does its improvising. This is the layer Capsule builds at, and it is the one that holds when a model decides that the fastest way to finish a task is to send your data somewhere it was never meant to go.
This runs quietly in production, across every major model, in the ordinary course of asking an assistant to do ordinary work: the model reaches for the most common recipe on the internet, the sandbox covers one path and misses another, and a file that should have stayed on a laptop ends up on a stranger's server, with a link posted where someone will happily click it. The people it happens to have no reason to suspect that anything went wrong. We have already seen it move files in production, and we are concerned the same has happened in other environments without anyone noticing, so any team running Cursor at scale should comb its logs for agent-initiated uploads to these hosts before assuming it has not. We reported it, we waited, and we are publishing now because silence is the one response that guarantees it keeps happening.

Modern AI agents are increasingly causing critical system damage not through external cyberattacks, but by taking unprompted, off-script actions across unguarded tools like databases and system shells. Traditional safeguards, including prompt instructions and human approval workflows, routinely fail to catch these autonomous errors before execution. To mitigate this growing risk, security must shift directly to the tool-call boundary, enforcing deterministic runtime controls that intercept and block destructive commands before they run.

Capsule launches a security integration for Claude Platform, using Claude's Compliance API to give security, compliance, and AI governance teams visibility into enterprise AI activity, risk, and posture across Anthropic-hosted deployments.

Our analysis of 206,435 AI agent skills reveals a rapidly growing software supply chain vulnerable to natural language payloads and dangerous capability combinations. Read the report to understand how these skills bypass traditional security controls and learn how Capsule protects your organization by securing the agent runtime.
.png)
The theoretical phase of agentic AI security is over—the attack surface is real and the incidents are documented. This post breaks down the defensive architecture taking shape in response: Meta's Agents Rule of Two, deterministic enforcement hooks, identity governance for non-human agents, and the questions security leaders need to be asking right now.

The security risks of AI agents are no longer theoretical. This blog examines the active threat landscape facing agentic AI in 2026, from prompt injection and supply chain attacks against MCP and skill registries to the governance gap created by vibe coding and Shadow AI.

Guardian agents are emerging as a critical security layer for the agentic AI era. As enterprises adopt AI agents that execute tools, handle sensitive data, and operate inside real workflows, human approval loops no longer scale. Guardian agents solve this by supervising other agents in real time: monitoring actions, enforcing policy, and blocking risky behavior before execution.
.png)
Capsule found two Cursor IDE vulnerabilities that let hidden prompt-injection instructions in referenced files steal developers’ SSH keys and contaminate future unrelated projects, causing zero-click or one-click exfiltration even when the attacker ships no malicious code.

Capsule Security’s State of AI Agent Security 2026 report is the largest independent audit of AI agents to date, showing that the ecosystem is rapidly shipping publicly exposed, weakly guarded, highly connected agents with recurring misconfigurations, near-absent runtime controls, widespread prompt-injection risk, expanding supply-chain exposure, and active malicious campaigns still propagating through agent skill and tool registries.

Capsule is launching a runtime security platform for the agentic AI era, built to monitor and stop autonomous agents that can bypass traditional guardrails, misuse legitimate access, and create a new class of enterprise security risk.

Capsule research team discover a critical prompt injection vulnerability in Salesforce Agentforce that allows attackers to exfiltrate CRM data through a simple lead from a form submission. No authentication required.