GHSA-489g-7rxv-6c8q: MCP Atlassian: DNS-rebinding TOCTOU bypass of the SSRF fix (CVE-2026-27826)
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-atlassianA 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.0The 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 IPservers/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 entriesCVE-2026-77361
obsidian-tc : Symlink read-ACL scope bypass via lexical path checks
medium4.7Oct 23, 2026CVE-2026-114126
Storybook dev server vulnerable to code injection from the local network
high8.7Oct 22, 2026CVE-2026-113731
djust: Arbitrary absolute-path file read in the find_handlers_for_template MCP tool
low3.3Oct 21, 2026CVE-2026-114125
Storybook: Missing origin validation in Storybook preview allows code injection from malicious websites
critical9.4Oct 21, 2026CVE-2026-111770
MCP TypeScript server SDK: Shared transport or server instances delivered one HTTP client's messages to another
high7.7Oct 20, 2026GHSA-953h-535j-jg2v
agent-router: MCP session resume does not verify the embedded anti-hijacking subject; default Helm seed makes session IDs forgeable
medium6.8Oct 19, 2026
