Sentry MCP
npm:@sentry/mcp-server@0.35.0
Severity breakdown
Worst finding
Tool `update_issue` name implies a side effect that is not declared
· update_issue
`update_issue` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
All 10 findings
- highTool `update_issue` name implies a side effect that is not declared· update_issueexcessive agency
`update_issue` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- highTool `create_team` name implies a side effect that is not declared· create_teamexcessive agency
`create_team` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- highTool `create_project` name implies a side effect that is not declared· create_projectexcessive agency
`create_project` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- highTool `update_project` name implies a side effect that is not declared· update_projectexcessive agency
`update_project` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- highTool `create_dsn` name implies a side effect that is not declared· create_dsnexcessive agency
`create_dsn` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- mediumTool `get_event_attachment` fetches external web content -- indirect-injection surface· get_event_attachmentindirect injection
Description: "Download attachments from a Sentry event. Use this tool when you need to: - Download files attached to a specific event - Access screenshots, log files, or other attachments uploaded with an error report - Retrieve attachment metadata and download URLs <examples> ### Download a specific attachment by ID ``` get_event_attachment(organizationSlug='my-organization', projectSlug='my-project', eventId='c49541c747cb4d8aa3efb70ca5aba243', attachmentId='12345') ``` ### List all attachments for an event ``` get_event_attachment(organizationSlug='my-organization', projectSlug='my-project', eventId='c49541c747cb4d8aa3efb70ca5aba243') ``` </examples> <hints> - If `attachmentId` is provided, the specific attachment will be downloaded as an embedded resource - If `attachmentId` is omitted, all attachments for the event will be listed with download information - The `projectSlug` is required to identify which project the event belongs to </hints>" -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.
fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.
- mediumTool `get_doc` accepts unconstrained string input· get_docunconstrained input
The following string parameter(s) have no `maxLength` constraint: `path`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `get_doc` fetches external web content -- indirect-injection surface· get_docindirect injection
Description: "Fetch the full markdown content of a Sentry documentation page. Use this tool when you need to: - Read the complete documentation for a specific topic - Get detailed implementation examples or code snippets - Access the full context of a documentation page - Extract specific sections from documentation <examples> ### Get the Next.js integration guide ``` get_doc(path='/platforms/javascript/guides/nextjs.md') ``` </examples> <hints> - Use the path from search_docs results for accurate fetching - Paths should end with .md extension </hints>" -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.
fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.
- mediumTool `get_sentry_resource` accepts unconstrained string input· get_sentry_resourceunconstrained input
The following string parameter(s) have no `maxLength` constraint: `organizationSlug`, `resourceId`, `resourceType`, `url`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `get_sentry_resource` fetches external web content -- indirect-injection surface· get_sentry_resourceindirect injection
Description: "Fetch a Sentry resource by URL or by type and ID. Pass a Sentry URL directly and the resource type is auto-detected. Supports issues, events, traces, spans, AI conversations, replays, breadcrumbs, and preprod snapshots. Sentry URLs require authentication that this tool handles. Trace lookups return a condensed overview by default. For preprod snapshot URLs (matching 'sentry.io/preprod/snapshots/'): - Without ?selectedSnapshot=: returns the snapshot diff summary (changed, added, removed images) - With ?selectedSnapshot=<image_file_name>: returns the specific image and full metadata For `resourceType='span'`, pass `resourceId` as `<traceId>:<spanId>`. <examples> ### From a Sentry URL get_sentry_resource(url='https://sentry.io/issues/PROJECT-123/') ### Breadcrumbs from a Sentry URL get_sentry_resource(url='https://sentry.io/issues/PROJECT-123/', resourceType='breadcrumbs') ### By type and ID get_sentry_resource(resourceType='issue', organizationSlug='my-org', resourceId='PROJECT-123') ### Span by trace and span ID get_sentry_resource(resourceType='span', organizationSlug='my-org', resourceId='a4d1aae7216b47ff8117cf4e09ce9d0a:aa8e7f3384ef4ff5') ### Replay by ID get_sentry_resource(resourceType='replay', organizationSlug='my-org', resourceId='7e07485f-12f9-416b-8b14-26260799b51f') ### AI conversation by ID get_sentry_resource(resourceType='ai_conversation', organizationSlug='my-org', resourceId='conversation-123') ### Investigate a failed snapshot test from CI get_sentry_resource(url='https://sentry.sentry.io/preprod/snapshots/241539/') ### View a specific changed snapshot image get_sentry_resource(url='https://sentry.sentry.io/preprod/snapshots/241539/?selectedSnapshot=login_screen.png') </examples>" -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.
fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.
How this was scored
Source sandbox — live tools/list captured in an ephemeral Docker container (parameter schemas included → R1/R2/R4 fire). Findings are emitted by the public capframe.findings.v1 schema. Score = 100 − (10·Critical + 4·High + 2·Medium + 1·Low), clamped to [0, 100].
Disagree with a finding? Open an issue.