VDB
Sign up
HIGH8.8

GHSA-3r68-hf9h-887v

MCP Atlassian: ENABLED_TOOLS / Toolset authorization bypass

Quick fix

GHSA-3r68-hf9h-887v — mcp-atlassian: upgrade to the fixed version with the command below.

pip install --upgrade 'mcp-atlassian>=0.22.0'

Details

### Summary

`ENABLED_TOOLS` and `TOOLSETS` filters are enforced at `tools/list` time only. `tools/call` dispatches from the full unfiltered tool registry (73 tools). Any user with access to the server endpoint that knows a tool name can invoke it directly. Tool names are not secret since mcp-atlassian is open source. Any direct JSON-RPC call bypasses the restriction entirely.

`READ_ONLY_MODE` is **not** affected: it has dual enforcement at list time (`_list_tools_mcp`) and call time `@check_write_access decorator`. The developers applied the correct pattern to `READ_ONLY_MODE` but not to `ENABLED_TOOLS` or `toolsets` - confirming this is an implementation oversight.

### Impact

Any user with access to the MCP server's HTTP endpoint can invoke any of the 73 registered tools regardless of `ENABLED_TOOLS` or `TOOLSETS` configuration - including write and delete operations on Jira issues, Confluence pages, etc. Operators deploying mcp-atlassian via Streamable HTTP rely on `ENABLED_TOOLS` to enforce least-privilege access; the bypass invalidates that model entirely.

The security impact concentrates in multi-user / HTTP-transport deployments, where the tool filter is a trust boundary between clients. In a single-user stdio deployment there is no second principal to defend against.

### Details In `src/mcp_atlassian/servers/main.py`, AtlassianMCP overrides `_list_tools_mcp` and applies the `TOOLSETS` and `ENABLED_TOOLS` filters before returning the tool list to clients. The `_call_tool_mcp` handler is not overridden. FastMCP's default `_call_tool_mcp` resolves the tool from the local tool manager / mounted servers, the full unfiltered inventory, so the filters never apply at call time.

### Proof of Concept

All calls are issued against the HTTP transport, with `ENABLED_TOOLS=jira_search` configured - only `jira_search` should be reachable.

Step 1 - negative control: tools/list correctly filters by ENABLED_TOOLS: ``` req → tools/list ← { "tools": [ { "name": "jira_search" } ] } # only 1 tool; jira_get_issue / jira_create_issue absent ```

Step 2 - confidentiality bypass: tools/call dispatches jira_get_issue despite its exclusion from the list: ``` req → tools/call jira_get_issue { "issue_key": "SEC-1" } ← { ... issue fields (summary, status, ...) ... } # executed; not blocked ```

Step 3 - integrity bypass: tools/call dispatches the write tool jira_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 ```

Step 1 proves the filter exists and is enforced at list time, so Steps 2–3 are a genuine authorization bypass, not an open/unconfigured endpoint. The same result holds with TOOLSETS=jira_read configured: write tools are absent from tools/list yet execute via tools/call.

**Local reproduction**

Extract `enabled_tools_bypass_tool_authorization.zip`: ``` # Fill Atlassian credentials in docker-compose.yml (ENABLED_TOOLS=jira_search is preset); # ensure issue SEC-1 exists, or update the project/issue key in poc.sh docker compose up -d # mcp-atlassian, streamable-http, 0.0.0.0, ENABLED_TOOLS=jira_search ./poc.sh # exits 0 on success docker compose down -v ```

>Requires Docker, curl, jq, and an Atlassian Cloud site with a Jira project (free tier works). The script runs the three steps above: it confirms tools/list returns only jira_search, then dispatches the excluded jira_get_issue (read) and jira_create_issue (write) via tools/call. The test issue it creates is deleted automatically on exit.

### Credit Discovered by [Francisco Rosales](https://www.linkedin.com/in/francisco-rosales-celis/) of [Manifold Security](https://manifold.security/)

Are you affected?

Enter the version of the package you're using.

Affected packages

PyPI/mcp-atlassian
Introduced in: 0Fixed in: 0.22.0
Fixpip install --upgrade 'mcp-atlassian>=0.22.0'

References