Agentjacking: Sentry MCP Injection Turns Observability Telemetry into Code Execution

high · Disclosed · 5 min read

A Sentry Data Source Name is public by design, embedded in every web application's frontend JavaScript. Tenet Security found that posting a crafted error event to Sentry's ingest endpoint, using only that public credential, causes AI coding agents to execute attacker-controlled commands when they next query Sentry via MCP. No phishing, no stolen credentials, no policy violations. In controlled testing across Claude Code, Cursor, and Codex, the attack succeeded 85 per cent of the time and exposed AWS keys, GitHub tokens, and private repository URLs. Tenet identified 2,388 organisations with injectable DSNs. Sentry acknowledged the disclosure and called it technically not defensible, deploying only a string-match filter against the specific known payload.

What happened

Sentry DSNs are write-only credentials that appear in any website's source code. They are supposed to be public. Sentry documents this explicitly: the DSN is safe to embed in client JavaScript because it only allows event submission, not data reads. That framing is correct for a human developer looking at Sentry's dashboard. It stops being correct when an AI coding agent is wired to Sentry via MCP and trusted to act on what it finds there.

The attack chain Tenet Security documented is called Agentjacking. An attacker retrieves a target organisation's Sentry DSN from the application's JavaScript or a GitHub search, then posts a crafted error event via a normal HTTP POST to Sentry's ingest endpoint. The event uses carefully formatted markdown in its message field: plausible-looking error context, a fake resolution section, and an npx command disguised as a recommended fix step. No authentication beyond the DSN is required at any point.

When a developer asks their AI coding agent to fix unresolved Sentry issues, the agent queries Sentry via the Sentry MCP server. The injected event is returned alongside legitimate errors, visually and structurally indistinguishable from Sentry's own template output. The agent does not distinguish between events generated by a real application crash and events posted by an attacker. It interprets the fake resolution steps as legitimate diagnostic guidance and executes the embedded command, running an attacker-controlled npm package with the developer's full local privileges.

The package then reads environment variables, AWS credentials, cloud configuration, Git credentials, private repository URLs, and developer identity data, and transmits them back. Every step in the chain is authorised. The agent performs only operations it was given permission to do. No EDR signature fires, no WAF inspects the traffic, no IAM policy triggers. Sentry described comprehensive fixes as technically not defensible and deployed only a content filter targeting the specific payload string Tenet used, which any variant payload circumvents.

The PolicyLayer angle

Agentjacking is the Authorized Intent Chain made concrete: every action the agent took was permitted, which is why every existing security control missed it. The point of failure is not the agent's model, not the Sentry MCP server, and not the developer's network. It is the absence of a boundary that asks, before the agent executes a command it found in tool output: was this instruction issued by the user, or did it arrive in data the tool retrieved?

The specific controls that break this attack: first, deny-by-default on command execution from tool output. MCP tool responses are data, not instructions. An agent policy that requires explicit user approval before running any command found in the body of a tool response would have stopped the Sentry PoC at the last step, regardless of how convincing the injected content was. Second, content provenance labelling at the MCP tool boundary. Sentry's MCP server could annotate its responses with a signal indicating that event content is externally submitted user data, not platform-generated output. An agent policy that treats annotated-untrusted content as read-only context rather than instruction surface would contain the class permanently. Third, scoped credentials. If the developer's environment variables do not contain production AWS keys during normal debugging sessions, the payload has nothing to exfiltrate.

Tenet open-sourced a set of drop-in Cursor and Claude Code configurations called agent-jackstop that implement the first control as a practical starting point. These are mitigations the developer can deploy today without waiting for Sentry to change its architecture or the protocol to add content-integrity semantics.

Mitigations

Apply Tenet Security's open-source agent-jackstop configurations for Cursor and Claude Code, which constrain agent command execution from untrusted tool output. Review and restrict which Sentry projects are accessible via your MCP integration. Do not grant MCP-connected agents ambient access to production cloud credentials: use short-lived, task-scoped tokens instead. For any workflow where an agent queries observability platforms, require human confirmation before executing commands surfaced from those queries. Monitor for npx or npm install invocations that originate from the AI agent process rather than the developer's terminal.

FAQs

Does Sentry plan to fix this? +

Sentry has characterised the root cause as technically not defensible at the platform level. The company implemented a content filter targeting the specific payload string from the disclosure, which any attacker with awareness of the research can trivially bypass by varying the markdown structure. Root-cause remediation would require either restricting event ingestion to authenticated sources or sanitising event data before it is returned via the MCP server; Sentry described neither as feasible.

Does the attack work even if the developer is not actively debugging? +

The attack triggers when the developer instructs the AI agent to investigate unresolved Sentry issues, which is a routine developer prompt. It does not require the developer to open the Sentry dashboard or take any action beyond that standard workflow. Once a fake event is in the queue, it waits for the next routine debugging session.

Is this specific to Sentry, or does the same class apply elsewhere? +

VentureBeat and others noted that any observability platform with open event ingestion and an MCP integration shares the same structural exposure, citing Datadog, PagerDuty, and Jira as examples with similar architectures. The attack surface is the combination of externally writable event stores and MCP servers that return their contents to agents as trusted output, not the Sentry implementation specifically.

References

Take your agents live. Without losing control.

Route your MCP traffic through PolicyLayer. Every tool call is checked against your policy before it runs: allow, deny, or require approval. Per-identity grants. Full audit log. Live in minutes.

Instant setup, no code required.

46,500+ MCP servers and 515,000+ tools scanned and risk-classified.

// GET IN TOUCH

Have a question or want to learn more? Send us a message.

Message sent.

We'll get back to you soon.