NewApp Monitoring is liveSign up free
AgentbeamBeta
AI agent vulnerability · Other MCP servers and tools

GHSA-489g-7rxv-6c8q: MCP Atlassian: DNS-rebinding TOCTOU bypass of the SSRF fix (CVE-2026-27826)

mediumCVSS 3.1 6.5

The SSRF fix in mcp-atlassian for CVE-2026-27826 can be bypassed with DNS rebinding. The guard resolves the host from the `X-Atlassian-Jira-Url` or `X-Atlassian-Confluence-Url` header once, then the outbound request resolves it again with no IP pinned. Versions before 0.22.0 are affected. Exploiting it needs an attacker-run rebinding DNS server.

Published Jul 10, 2026 · Analysis Oct 25, 2026

What an attacker can do

validate_url_for_ssrf in src/mcp_atlassian/utils/urls.py resolves the header host, checks that each address is global, and returns only an error string or None. The validated IP is thrown away. servers/main.py calls it once in middleware. Then servers/dependencies.py builds the fetcher from the raw header hostname, so the real request does a second lookup at connect time.

An attacker who controls a DNS name can answer the first lookup with a public address, which passes, and the second with 169.254.169.254 or an internal address, which the socket then connects to. That reaches cloud metadata, such as IAM credentials, or internal services, on a build that was supposed to be patched. The headers are handled in UserTokenMiddleware before the fetcher is created, so an unauthenticated or low-privilege caller picks the host.

The reporter is explicit about the limits. The PoC loads the real urls.py and simulates the two lookups with getaddrinfo. It proves the missing pin, not a live end-to-end exploit on a running server. A real attack must win the race window between check and connect with a fast-rebinding DNS responder. That is why the rating is medium (AC:H).

Who is affected

PyPI package mcp-atlassian before 0.22.0, on servers that accept the X-Atlassian-Jira-Url and X-Atlassian-Confluence-Url request headers, meaning remote HTTP deployments that serve multiple users. The advisory was written against a build that already contained the original SSRF fix (0.17.0 and later). Check the version:

pip show mcp-atlassian

A single-user stdio setup does not take these headers from remote callers.

mcp-atlassian

Ecosystem
PyPI
Affected
< 0.22.0
Fixed in
0.22.0
Check
pip show mcp-atlassian

How to fix it

Upgrade to mcp-atlassian 0.22.0:

pip install --upgrade mcp-atlassian==0.22.0

The version data lists 0.22.0 as patched. The 0.22.0 release notes I read describe the attachment path validation and do not mention DNS pinning, so confirm in the advisory that this release carries the rebinding fix. The reporter's remediation is to pin the connection to the validated IP, using a custom resolver or a cached-getaddrinfo adapter, or by passing the IP with a Host header. As a network control, block the metadata address from the server's host and use IMDSv2 on cloud hosts.

How to tell if you were hit

Look at server logs for requests with X-Atlassian-Jira-Url or X-Atlassian-Confluence-Url headers that name hosts outside your Atlassian domains, especially hostnames with very short DNS TTLs. On the network, watch for connections from the MCP server to 169.254.169.254 or private ranges that follow such requests. Cloud audit logs showing the instance role's credentials used from unexpected addresses can signal metadata theft.

Original advisory

From the GitHub Advisory Database (CC BY 4.0).

Summary

GHSA-7r34-79r5-rcc9's fix added validate_url_for_ssrf, which resolves the attacker-controlled X-Atlassian-{Jira,Confluence}-Url header host once at middleware time and trusts the result. But the outbound request is later built with the raw hostname and re-resolves at connect time with no IP pinning. An attacker-controlled rebinding DNS name returns a public IP on the guard's lookup (validation passes) and 169.254.169.254 / an internal IP on the request's lookup (the socket connects there) → unauthenticated SSRF to cloud metadata / internal services on the patched build.

Relationship to CVE-2026-27826 / GHSA-7r34-79r5-rcc9 (incomplete fix — please read first)

This is an incomplete-fix sibling of the published GHSA-7r34-79r5-rcc9 (the X-Atlassian-*-Url header SSRF). That fix (PR #986/#1005) added a single middleware-time resolve + allowlist DNS-skip, but does not pin the validated IP to the connection — the fetcher re-resolves the raw hostname at connect time, so the documented SSRF mitigation is incomplete against DNS-rebinding. The other advisory GHSA-xjgw-4wvw-rgm4 (file-write) is unrelated. Verified live (2026-06-27): neither advisory, nor any open PR/issue (rebind/TOCTOU/getaddrinfo/pin → 0), covers connect-time re-resolution. Filing as an incomplete-fix of GHSA-7r34 (not a standalone fresh SSRF).

Affected

src/mcp_atlassian/utils/urls.py + servers/main.py + servers/dependencies.py, HEAD ba72540 (PyPI mcp-atlassian, patched ≥0.17.0). CWE-918 (SSRF) via CWE-367 (TOCTOU).

Vulnerable code

utils/urls.py validate_url_for_ssrf (≈184-205) resolves + validates, then returns a string verdict, not a pinned IP:

def validate_url_for_ssrf(url: str) -> str | None:   # returns an error string or None — NO IP is pinned
    ...
    # resolves the host, checks each resolved IP is global, then DISCARDS the IP

servers/main.py:526,534 calls it once in middleware. servers/dependencies.py:544-561 then builds the fetcher with url = <raw header hostname> (no pinned IP, no custom resolver / cached-getaddrinfo adapter), so the actual request re-resolves the name.

PoC (executed — boundary demonstration)

The PoC loads the real urls.py by path (importlib, sha256 printed) and drives the genuine validate_url_for_ssrf, simulating the two resolutions via getaddrinfo:

[CHECK ] validate_url_for_ssrf('http://rebind.attacker.example') -> None        (getaddrinfo#1 = 93.184.216.34 global -> guard PASSED)
[CONNECT] getaddrinfo call #2 returned 169.254.169.254 -> the socket connects HERE
[PROOF ] guard validated IP 93.184.216.34 but connection targets 169.254.169.254  => SSRF on the PATCHED build
[CONTROL] if guard SAW 169.254.169.254 at check time -> blocks it correctly
[PIN   ] validate_url_for_ssrf returns a verdict (None), NOT an IP; dependencies.py builds url=raw hostname -> NO pin
ALL PoC ASSERTIONS PASSED — DNS-rebind TOCTOU bypass demonstrated.

Honest scope of the PoC: this is a boundary demonstration — it proves the structural TOCTOU (the guard validates an IP it then discards; the connection re-resolves an unpinned hostname). It does not demonstrate a live end-to-end SSRF on a running server; that additionally requires an attacker-controlled fast-rebinding authoritative DNS responder winning the resolve→connect window. Flagging this explicitly rather than overclaiming.

Impact

Same as parent GHSA-7r34 (unauth read of cloud-metadata IAM creds / internal-service reach), reachable again on the patched version. The X-Atlassian-*-Url headers are processed in UserTokenMiddleware before fetcher creation, so an unauthenticated/low-priv caller controls the host.

Severity

High — CVSS v3.1 `AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N` ≈ 7.x, aligned to the parent (8.2) with AC:H for the rebinding-race precondition. Honest caveat (above): the executed PoC proves the missing IP-pin structurally; a live exploit additionally needs an attacker rebinding-DNS. Not Critical.

Remediation

Pin the connection to the IP that validate_url_for_ssrf validated: use a custom resolver / cached-getaddrinfo requests-adapter (or pass the validated IP with a Host header), so the connect cannot re-resolve to a different address.

Dedup / freshness (re-verified live 2026-06-27)

Advisories GHSA-7r34-79r5-rcc9 (original header SSRF this bypasses) + GHSA-xjgw-4wvw-rgm4 (file-write, unrelated). Neither covers connect-time re-resolution / rebinding. PR #986/#1005 (the fix) add a single middleware-time resolve + allowlist DNS-skip, no pinning. gh search prs/issues for rebind/TOCTOU/getaddrinfo/pin → 0. First-party code. Fresh at HEAD ba72540.

Credited to daniel-mertz.

Questions

Is this a new SSRF or a bypass of CVE-2026-27826?

It is an incomplete-fix sibling. The earlier fix validates the host once, and the connection re-resolves it later without pinning, so DNS rebinding defeats the check.

Is it exploitable in practice?

The reporter proved the missing IP pin structurally but not a live exploit. An attacker needs a rebinding DNS responder that wins the race between check and connect.

What can the attacker reach?

Per the advisory, the same as the parent issue: cloud metadata such as IAM credentials, and internal services the MCP server can reach.

References

How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology

More Other MCP servers and tools vulnerabilities

All Other MCP servers and tools entries