Skip to content

Back to the catalog

AI Security Briefing
github.comadvisory

AI Security Briefing

This GHSA advisory documents CVE-2026-27826, a DNS-rebinding TOCTOU bypass of the SSRF fix in the MCP Atlassian server (mcp-atlassian PyPI package). The prior patch (GHSA-7r34-79r5-rcc9) added validate_url_for_ssrf, which resolves the attacker-controlled X-Atlassian-{Jira,Confluence}-Url header host once at middleware time but discards the resolved IP; the actual outbound request later re-resolves the raw hostname at connect time with no IP pinning, so a rebinding DNS name can pass validation with a public IP and then connect to 169.254.169.254 or an internal address, restoring unauthenticated SSRF to cloud metadata/internal services even on the 'patched' build. The advisory includes an executed PoC against the real urls.py, exact code locations (utils/urls.py, servers/main.py, servers/dependencies.py), and remediation via a custom resolver/cached-getaddrinfo adapter to pin the validated IP.

TL;DR CVE-2026-27826: MCP Atlassian's SSRF fix is bypassable via DNS-rebinding TOCTOU because the validated IP is never pinned to the actual connection.
Document

What it is

An incomplete-fix advisory for CVE-2026-27826 in mcp-atlassian (PyPI, patched ≥0.17.0, HEAD ba72540). It reopens the SSRF fixed in GHSA-7r34-79r5-rcc9 (the X-Atlassian-{Jira,Confluence}-Url header SSRF) by showing that fix — PR #986/#1005 — validates but never pins the resolved IP, leaving a DNS-rebinding TOCTOU window. Classified CWE-918 via CWE-367.

How it works

validate_url_for_ssrf in utils/urls.py (~184-205) resolves the attacker-controlled header host, checks each IP is global, then returns only a string verdict (None/error) — the validated IP is discarded. servers/main.py:526,534 calls it once in middleware; servers/dependencies.py:544-561 then builds the fetcher with the raw hostname, so the outbound request re-resolves at connect time with no pinned IP or custom resolver.

flowchart TD
    A[Header host] --> B[getaddrinfo #1: 93.184.216.34 global]
    B --> C{guard passes?}
    C -->|yes, IP discarded| D[fetcher built with raw hostname]
    D --> E[getaddrinfo #2: 169.254.169.254]
    E --> F[socket connects to metadata/internal]
    C -->|if guard saw 169.254...| G[correctly blocked]

Preconditions / Affected

  • Any version on the "patched" build (HEAD ba72540); the fix does not close this.
  • The X-Atlassian-*-Url headers are processed in UserTokenMiddleware before fetcher creation, so an unauthenticated / low-priv caller controls the host.
  • A live exploit additionally needs an attacker-controlled fast-rebinding authoritative DNS responder that wins the resolve→connect race.

What to do

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 directly with a Host header,

so the connect step cannot re-resolve to a different address.

Caveats

The author is explicit that the executed PoC is a boundary demonstration only: it loads the real urls.py by path (sha256 printed) and drives validate_url_for_ssrf, simulating the two resolutions to prove the structural TOCTOU (validated IP discarded, unpinned hostname re-resolved). It does not demonstrate live end-to-end SSRF on a running server. Severity is rated High, not Critical — CVSS v3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N (≈7.x), with AC:H reflecting the rebinding-race precondition, versus the parent's 8.2. As of 2026-06-27 no advisory, PR, or issue covered connect-time re-resolution.

Organisations named here

  • CWE-918
  • GHSA-489g-7rxv-6c8q
  • GHSA-7r34-79r5-rcc9
  • GHSA-xjgw-4wvw-rgm4

CVEs named here

  • CVE-2026-27826

Technologies named here

  • mcp-atlassian
  • Model Context Protocol
  • PyPI
  • Python
  • Jira

Techniques named here

  • SSRF
  • TOCTOU
  • DNS rebinding
  • Time-of-check Time-of-use Race Condition