A public error-reporting key, a fake bug report, and a coding agent that runs the attacker's code with your credentials. This is not a Sentry bug. It is proof that "read this" and "act on what you read" have silently become the same permission.


TL;DR

  • An attacker posts a fake error to your Sentry project using a key that is public by design, disguises it as a legitimate "resolution" step, and waits. A developer asks their coding agent to fix unresolved issues; the agent reads the injected event over MCP and runs the attacker's code with the developer's own privileges.
  • Tenet Security, which named the attack "agentjacking" in June 2026, found 2,388 organizations with injectable Sentry keys (exposure at scale, not confirmed compromise of each) and hijacked agents 85% of the time across 100-plus controlled tests, including one it valued at roughly $250 billion.
  • The sharpest finding: agents ran the payload 85% of the time even when the system prompt explicitly told them to distrust tool output. A warning in a prompt is a request, not a boundary.
  • Every step in the chain is authorized. No credential is stolen, no policy is broken, no perimeter is crossed, so EDR, WAF, IAM, and firewalls see nothing.
  • This is not one vendor's flaw. The same shape applies to Datadog, PagerDuty, Jira, GitHub PR titles, support tickets, and the inbound email your GTM agent reads next.
  • The fix is architectural, not a filter: mark data by provenance and never let anything from outside your org boundary reach a component that can execute, exfiltrate, or change state without a human gate.

A developer opens their terminal and types "fix the unresolved Sentry issues." Their coding agent queries Sentry, reads back a list of errors, finds one with a tidy remediation note, and runs the suggested command. Thirty seconds later an attacker on the other side of the internet has the developer's AWS keys. No malware was installed. No password was phished. No firewall was touched. The developer did exactly what they do every day, and so did the agent.

That is agentjacking, and the reason it should worry anyone building with agents is not the cleverness of the exploit. It is how ordinary every step is.

The credential that was never a secret

Start with the thing everyone gets wrong. The key at the center of this is a Sentry DSN, and Sentry documents it as safe to embed in your frontend JavaScript. It has to be public: any browser running your app must be able to report errors to Sentry's ingest endpoint without an authenticated session. The DSN is a write-only credential whose whole job is to be exposed.

So an attacker does not steal anything. They read your DSN out of your public JavaScript (or find it with a GitHub search), then POST a crafted error event to Sentry's ingest endpoint. Into the message and context fields, they inject markdown formatted to look exactly like Sentry's own remediation template, "visually and structurally indistinguishable" from legitimate guidance, in Tenet's words. The payload sits in your project as just another unresolved issue.

The trap springs later, when a human asks an agent to clean up the backlog. The agent queries Sentry over MCP, receives the injected event as authentic tool output, and executes the embedded instruction, something like npx <attacker-package> --diagnose, with the developer's privileges. The package beacons home and starts reading environment variables. Tenet confirmed exfiltration of AWS secret keys, GitHub and GitLab OAuth tokens, SSH agent sockets, Kubernetes cluster tokens, npm registry tokens, and CI/CD secrets from tested machines.

The leaked thing was never a credential. It was capability, granted implicitly the moment an untrusted feed was wired into a privileged agent. This is why the obvious reactions all miss. You cannot rotate a key that is public by design. You cannot hide it; the product does not work if you do. And a WAF, an EDR, an IAM policy, a VPN all see a trusted developer's own tooling doing authorized things. Every action in the chain is legitimate. Nothing in a CVE database catches a permission you granted on purpose to the wrong party.

This is a shape, not a Sentry bug

Sentry is one instance. The generalizable pattern is this: any tool that (a) accepts data written by people outside your organization and (b) hands that data to an agent that treats tool output as trusted, in a session where the agent can also act, is exploitable the same way.

VentureBeat put the generalization in its headline: the attack came through Sentry, but Datadog, PagerDuty, and Jira have the same exposure. The framing is exactly the builder's test: if your agents are connected to Sentry, Datadog, PagerDuty, Jira, or any MCP-connected source your developers trust, and those agents can execute shell commands, then your stack has the same blind spot. Observability tools ingest error payloads. Incident tools ingest alert bodies. Ticketing tools ingest descriptions written by anyone who can open a ticket. All of it becomes agent context. Barak Sternberg, Tenet's co-founder, put the real lesson plainly: the data an agent reads "now includes telemetry, logs, tickets, and tool output that nobody ever treated as an attack surface." The Cloud Security Alliance agreed quickly, classifying agentjacking as a systemic MCP vulnerability class within days of the disclosure.

And this is not theoretical outside coding. In April 2026, security researcher Aonan Guan, working with Johns Hopkins collaborators, hijacked Claude Code, Gemini CLI, and GitHub Copilot by planting instructions in GitHub PR titles and comments, the "Comment and Control" attack. In 2025 Supabase's Cursor agent, running with privileged database access, processed support tickets containing user-supplied text; attackers embedded SQL that read and exfiltrated integration tokens. OWASP has a name for the tool-side version, "MCP Tool Poisoning," and the root cause it documents is blunt: MCP clients pass tool responses into the model's context as-is, and the spec does not require validating that output before it reaches the model.

The cleanest frame is Simon Willison's "lethal trifecta": an agent that simultaneously has access to private data, exposure to untrusted content, and the ability to act or communicate externally. Hold any two and you are safe. Grant all three in one session and untrusted content can drive exfiltration with no exploit code at all. Agentjacking is a textbook trifecta: the dev machine holds credentials, the Sentry feed is untrusted, and the shell is the exit. Meta's "Agents Rule of Two" says the same thing prescriptively: an agent should satisfy no more than two of those three properties autonomously, and if it needs all three, it should not run without a human in the loop.

The permission you think you granted, and the one you actually granted

Here is the principle the news coverage keeps circling but rarely states. "Read access" and "act on what you read" have silently fused into a single permission, and the industry keeps granting the second while believing it granted the first.

An MCP integration you set up as "read-only Sentry access" sounds harmless. It reads; it cannot write. But the moment its output can steer an agent that also holds a shell, that read-only integration is effectively an execute grant to anyone on the internet who can write a Sentry event. Which, given a public DSN, is everyone. The permission on the label (read) and the permission in effect (execute, exposed to the public) are two different things, and the gap between them is where the entire attack lives.

The correct architectural primitive follows directly. Treat provenance as a first-class property of data. Anything that originated outside your org boundary gets structurally marked as untrusted, and marked data must never reach a component that can execute code, exfiltrate data, or change state without a human gate in between. Not "the agent should be careful with it." Structurally cannot reach it. This is the same instinct that made us stop concatenating user input into SQL strings two decades ago; we are relearning it one layer up, for prose instead of queries.

Why the obvious fixes fail, and what actually helps

The single most important number in this whole story is not the 2,388 exposed orgs. It is that agents ran the payload 85% of the time even when the system prompt explicitly instructed them to distrust tool output and never execute external commands without confirmation. Tenet's phrasing: agents executed the payload "even when explicitly instructed, through detailed system prompts and skills, to ignore untrusted data." Sternberg said it more bluntly still: "we told agents to distrust the input; they ran the payload anyway."

Sit with what that kills. A warning in a system prompt is a request, not a boundary. You cannot instruction-tune your way out of a capability boundary, because the same channel that carries your instructions carries the attacker's, and the model has no reliable way to rank yours above theirs. Prompt hygiene is not a security control. Neither is Sentry's actual response, a global content filter that blocks a specific payload string; that patches one string and leaves the class wide open. Sentry, to be fair, called the issue "technically not defensible" and they are partly right: they cannot fix an agent that chooses to execute their output, and the DSN's openness is required for the product to exist. The accountability sits with whoever wires an untrusted feed into a privileged agent. That is the builder.

What actually reduces blast radius, roughly in order of effectiveness per Tenet's own open-source agent-jackstop tool:

  1. Deny-by-default network egress. If the malicious package cannot be fetched and the beacon cannot phone home, the chain breaks at both ends. The authors rank this most effective.
  2. A human gate on consequential actions. Remove auto-run and bypass modes so a person approves anything that executes or changes state.
  3. Credential isolation. Block subprocess reads of ~/.aws, ~/.ssh, and .env so a hijacked agent has less to steal.
  4. Least-privilege, read-only, short-lived tool scopes, and a deliberately short list of connected MCPs.

Notice that agent instruction rules, telling the agent to distrust tool output, sit at the bottom of that ranking, and the tool's authors say so plainly: these configs reduce blast radius, they do not make an agent immune to prompt injection. Architecture patches the class. Signatures patch one string.

Where read became execute in your system

The coding-agent story is vivid because credentials and shells make the damage obvious. But the shape does not care whether the agent writes code. A GTM agent that reads an inbound prospect email and then drafts and sends a reply is the same trifecta: private data (your CRM), untrusted content (an email from anyone), and an external action (the send). A support agent that reads a ticket and updates a record is the same trifecta. The vivid instance is a developer's terminal; your own exposure is probably an ops or revenue agent you shipped last quarter and stopped thinking about.

So the useful question is not "which vendor is next." It is the builder's version: in my own system, where has read quietly become execute, and who outside my walls can write to that read? Trace every feed your agents consume back to who can put text in it. Wherever that list includes "the public," you have found a boundary that needs a valve.

There is a deeper seam here worth naming once. The same capability that lets an agent act on our behalf, reading intent from language and turning it into action, is exactly what lets an outsider act through it by writing the right language into a feed the agent trusts. Machines that act on text they were never meant to trust are the whole game now, offense and defense both. Build the valve before someone else finds the pipe.