# MCP Atlassian: ENABLED_TOOLS / Toolset authorization bypass

mcp-atlassian enforced ENABLED_TOOLS/TOOLSETS only at tools/list, so any HTTP client could call excluded Jira read/write tools via tools/call.

- Payout: Research
- Severity: high
- Program: mcp-atlassian
- Found by: 0xmagic0
- Disclosed: 2026-09-22
- CVE: CVE-2026-77243
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-3r68-hf9h-887v
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-3r68-hf9h-887v
- Tags: area:ai domain:ai domain:api impact:data-leak impact:integrity kind:research platform:ghsa sev:high tech:llm tech:rest technique:source-review vuln:access-control vuln:auth-bypass

**Target:** MCP server (Streamable HTTP transport) tool dispatch handler
**Root cause:** AtlassianMCP overrides _list_tools_mcp to apply TOOLSETS/ENABLED_TOOLS filters but does not override _call_tool_mcp, so FastMCP's default call handler resolves tools from the full unfiltered registry.
**Steps:**
1. Configure server with `ENABLED_TOOLS=jira_search` and start streamable-http transport.
2. Negative control: send `tools/list`; response contains only `jira_search`, confirming the filter is active.
3. Send `tools/call` for `jira_get_issue` with `{ "issue_key": "SEC-1" }`; issue fields are returned despite exclusion.
4. Send `tools/call` for `jira_create_issue` with `{ "project_key": "SEC", "summary": "[PoC] ENABLED_TOOLS bypass", "issue_type": "Task" }`; issue is created.
5. Repeat with `TOOLSETS=jira_read`: write tools absent from list yet execute via tools/call.
**How found:** Noticed READ_ONLY_MODE has dual enforcement (list-time filter plus @check_write_access decorator at call time) while ENABLED_TOOLS/TOOLSETS only filter in the overridden _list_tools_mcp; hypothesized the unoverridden _call_tool_mcp dispatches from the full registry and confirmed with a list-vs-call differential.
**Exploitation:** Any principal with network access to the MCP HTTP endpoint issues raw JSON-RPC tools/call requests naming tools from the open-source registry, reading or mutating Jira issues and Confluence pages that the operator intended to block.
**Escalation:** Read-only bypass (jira_get_issue) escalates to integrity impact by invoking write/delete tools such as jira_create_issue under the same filter.
**Insight:** When a framework exposes separate list and call handlers, a filter applied only in the list override is cosmetic; diff the two code paths and always test tools/call (or equivalent invoke endpoint) for names absent from the enumeration response.

## Proof of concept (copied exactly from the original report)

**tools/call bypasses ENABLED_TOOLS to read excluded issue**

```
req → tools/call jira_get_issue { "issue_key": "SEC-1" }
← { ... issue fields (summary, status, ...) ... }   # executed; not blocked
```

**tools/call bypasses ENABLED_TOOLS to create issue**

```
req → tools/call jira_create_issue
         { "project_key": "SEC", "summary": "[PoC] ENABLED_TOOLS bypass", "issue_type": "Task" }
← { ... "key": "SEC-<n>" ... }   # issue created despite ENABLED_TOOLS=jira_search
```

**Negative control tools/list filtered output**

```
req → tools/list
← { "tools": [ { "name": "jira_search" } ] }   # only 1 tool; jira_get_issue / jira_create_issue absent
```

