CVE-2026-77261
MCP Atlassian: SSRF redirect protection missing for basic-auth and OAuth authentication branches
MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, _make_ssrf_safe_hook is omitted from JiraFetcher and ConfluenceFetcher sessions created through the basic-auth and oauth_pat branches. If an attacker-controlled or compromised configured Atlassian instance returns a redirect to an internal address, those sessions can follow the redirect without revalidating its destination. This issue is fixed in version 0.22.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.1
MCP Atlassian: SSRF redirect protection missing for basic-auth and OAuth authentication branches
MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, _make_ssrf_safe_hook is omitted from JiraFetcher and ConfluenceFetcher sessions created through the basic-auth and oauth_pat branches. If an attacker-controlled or compromised configured Atlassian instance returns a redirect to an internal address, those sessions can follow the redirect without revalidating its destination. This issue is fixed in version 0.22.0.
- Record
CVE-2026-77261- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
EUVDEUVD-2026-84631
7.1
MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, _make_ssrf_safe_hook is omitted from JiraFetcher and ConfluenceFetcher sessions created through the basic-auth and oauth_pat branches. If an attacker-controlled or compromised configured Atlassian instance returns a redirect to an internal address, those sessions can follow the redirect without revalidating its destination. This issue is fixed in version 0.22.0.
- Record
EUVD-2026-84631- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-6529-c226-h328
7.1
MCP Atlassian: SSRF redirect protection missing for basic-auth and OAuth authentication branches
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:
# 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:
- Attacker controls or compromises an Atlassian instance (Cloud or Server)
- MCP server connects using basic auth or OAuth credentials (most production setups)
- Atlassian returns
302 Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/ - The unprotected session follows the redirect
- 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.
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:
<img width="2490" height="214" alt="image" src="https://github.com/user-attachments/assets/c7d9d7e2-4c37-4abd-95a3-4ddd9f6bd735" />
$ 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…
- Record
GHSA-6529-c226-h328- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
NVD
7.1
MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, _make_ssrf_safe_hook is omitted from JiraFetcher and ConfluenceFetcher sessions created through the basic-auth and oauth_pat branches. If an attacker-controlled or compromised configured Atlassian instance returns a redirect to an internal address, those sessions can follow the redirect without revalidating its destination. This issue is fixed in version 0.22.0.
- Record
CVE-2026-77261- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N - CVSS 3.1
- 8.5 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSV
7.1
MCP Atlassian: SSRF redirect protection missing for basic-auth and OAuth authentication branches
MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, _make_ssrf_safe_hook is omitted from JiraFetcher and ConfluenceFetcher sessions created through the basic-auth and oauth_pat branches. If an attacker-controlled or compromised configured Atlassian instance returns a redirect to an internal address, those sessions can follow the redirect without revalidating its destination. This issue is fixed in version 0.22.0.
- Record
CVE-2026-77261- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVGHSA-6529-c226-h328
7.1
MCP Atlassian: SSRF redirect protection missing for basic-auth and OAuth authentication branches
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:
# 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:
- Attacker controls or compromises an Atlassian instance (Cloud or Server)
- MCP server connects using basic auth or OAuth credentials (most production setups)
- Atlassian returns
302 Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/ - The unprotected session follows the redirect
- 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.
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:
<img width="2490" height="214" alt="image" src="https://github.com/user-attachments/assets/c7d9d7e2-4c37-4abd-95a3-4ddd9f6bd735" />
$ 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…
- Record
GHSA-6529-c226-h328- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVPYSEC-2026-4085
7.1
MCP Atlassian: SSRF redirect protection missing for basic-auth and OAuth authentication branches
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:
# 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:
- Attacker controls or compromises an Atlassian instance (Cloud or Server)
- MCP server connects using basic auth or OAuth credentials (most production setups)
- Atlassian returns
302 Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/ - The unprotected session follows the redirect
- 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.
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:
<img width="2490" height="214" alt="image" src="https://github.com/user-attachments/assets/c7d9d7e2-4c37-4abd-95a3-4ddd9f6bd735" />
$ 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…
- Record
PYSEC-2026-4085- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
mcp-atlassianPyPI |
before 0.22.0 | 0.22.0 |
mcp-atlassianPyPI |
before 0.22.0, plus listed versions 0.1.10.1.100.1.110.1.120.1.13 Show 45 moreShow less0.1.140.1.150.1.160.1.20.1.30.1.40.1.60.1.70.1.80.1.90.10.00.10.10.10.20.10.30.10.40.10.50.10.60.11.00.11.10.11.100.11.110.11.120.11.20.11.2a20.11.30.11.40.11.50.11.60.11.70.11.80.11.90.12.00.13.00.13.10.14.00.14.10.14.20.14.30.15.00.16.00.16.10.17.00.18.00.18.10.19.0 |
0.22.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-77261 is a high vulnerability (CVSS 7.1) in Mcp-atlassian Mcp Atlassian, published September 22, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.37%, the 31st percentile. Fixed in mcp-atlassian 0.22.0.
References
github.com/sooperset/mcp-atlassian/security/advisories/GHSA-6529-c226-h328
github.com/sooperset/mcp-atlassian/pull/1448
github.com/sooperset/mcp-atlassian/commit/b041733473f95119dd539542a43c280737a8e460
github.com/sooperset/mcp-atlassian/releases/tag/v0.22.0
nvd.nist.gov/vuln/detail/CVE-2026-77261
github.com/advisories/GHSA-6529-c226-h328
github.com/CVEProject/cvelistV5/tree/main/cves/2026/77xxx/CVE-2026-77261.json
github.com/sooperset/mcp-atlassian
pypi.org/project/mcp-atlassian
Left out here: 29 versions and the rest of 3 source descriptions. The JSON record has them.