GitHub Advisoryadvisory · PyPI
GHSA-6529-c226-h328 MCP Atlassian: SSRF redirect protection missing for basic-auth and OAuth authentication branches
HIGH
Official page ↗
- Aliases
- CVE-2026-77261
- Ecosystem
- PyPI
- Packages
- mcp-atlassian
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N
- Weaknesses
- CWE-918
- Reviewed
- 2026-09-22
Affected packages
• PyPI mcp-atlassian: < 0.22.0 → fixed in 0.22.0
Description
Summary
`_make_ssrf_safe_hook()` blocks HTTP redirects to private/internal IPs by validating the `Location` header before the client follows a `3xx` response. The problem is that this hook is only attached in one of three authentication branches — the header-PAT path. Basic auth and OAuth branches skip it entirely, so if the connected Atlassian server returns a redirect to something like `http://169.254.169.254/`, the `requests` session follows it without complaint.
This is an incomplete fix for GHSA-7r34-79r5-rcc9. The hook works fine when it's there — it just isn't there for most production auth configurations.
Details
In `src/mcp_atlassian/servers/dependencies.py`, three branches construct a fetcher and call `_create_and_validate()`. Only Branch 1 passes `attach_ssrf_hook=True`:
```python
Branch 1 (header PAT) — hook attached
return _create_and_validate(request, spec, header_config, "header_pat",
attach_ssrf_hook=True)
Branch 2 (basic auth) — hook missing
return _create_and_validate(request, spec, user_config, "basic",
user_email=user_email)
Branch 3 (OAuth/PAT) — hook missing
return _create_and_validate(request, spec, user_config, "oauth_pat",
user_email=user_email)
```
`attach_ssrf_hook` defaults to `False`, so branches 2 and 3 silently skip the protection. The hook itself (`_make_ssrf_safe_hook`) is straightforward — it checks `response.is_redirect`, grabs the `Location` header, and calls `validate_url_for_ssrf()` to reject private IPs. It works correctly when present.
Typical attack flow:
1. Attacker controls or compromises an Atlassian instance (Cloud or Server)
2. MCP server connects using basic auth or OAuth credentials (most production setups)
3. Atlassian returns `302 Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/`
4. The unprotected session follows the redirect
5. AWS IAM credentials (or other internal service data) are returned to the attacker
PoC
Tested on commit `d8bc786` (v0.21.1). No real credentials needed.
```python
from unittest.mock import MagicMock
import requests
from mcp_atlassian.servers.dependencies import _make_ssrf_safe_hook
from mcp_atlassian.utils.urls import validate_url_for_ssrf
from mcp_atlassian.jira import JiraFetcher
from mcp_atlassian.jira.config import JiraConfig
config = JiraConfig(
url="https://attacker.atlassian.net",
auth_type="basic",
username="[email protected]",
api_token="victim-token",
)
fetcher = JiraFetcher(config=config)
session = fetcher.jira._session
hooks = session.hooks.get("response", [])
print("hooks on basic-auth session:", [h.__name__ for h in hooks] or "none")
fake_redirect = MagicMock(spec=requests.Response)
fake_redirect.is_redirect = True
fake_redirect.headers = {"Location": "http://169.254.169.254/latest/meta-data/"}
blocked = False
for h in hooks:
try:
h(fake_redirect)
except ValueError as e:
blocked = True
print("blocked:", e)
if not blocked:
print("redirect to 169.254.169.254 not blocked on basic-auth session")
show header-PAT branch does block it
hook = _make_ssrf_safe_hook(validate_url_for_ssrf)
try:
hook(fake_redirect)
except ValueError as e:
print("header-PAT branch blocks:", e)
```
Output:
```
$ uv run python3 /tmp/test.py
hooks on basic-auth session: none
redirect to 169.254.169.254 not blocked on basic-auth session
header-PAT branch blocks: Redirect blocked (SSRF): Blocked IP address: 169.254.169.254 (non-global)
```
Impact
Basic auth and OAuth cover most production Atlassian Cloud deployments, so this affects the majority of HTTP-mode multi-user setups. An attacker with control over the Atlassian server can redirect MCP server requests to internal infrastructure — cloud metadata endpoints, internal Kubernetes API, databases, or any service reachable from the MCP server's network.
The fix is one line per affected branch: pass `attach_ssrf_hook=True` to `_create_and_validate()` in branches 2 and 3, the same way branch 1 already does.
Related
Alias · CVE (1)
- CVE-2026-77261 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
- https://github.com/sooperset/mcp-atlassian/security/advisories/GHSA-6529-c226-h328 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-77261 advisory
- https://github.com/sooperset/mcp-atlassian/pull/1448 web
- https://github.com/sooperset/mcp-atlassian/commit/b041733473f95119dd539542a43c280737a8e460 web
- https://github.com/sooperset/mcp-atlassian package
- https://github.com/sooperset/mcp-atlassian/releases/tag/v0.22.0 web