GitHub Advisoryadvisory · PyPI

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

HIGH Published 2026-09-22 Modified 2026-09-22 Official page ↗
Aliases
CVE-2026-77262
Ecosystem
PyPI
Packages
mcp-atlassian
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Weaknesses
CWE-22
Reviewed
2026-09-22

Affected packages

• PyPI mcp-atlassian: < 0.22.0 → fixed in 0.22.0

Description

Summary `mcp-atlassian` exposes an MCP tool `confluence_upload_attachment` whose `file_path` argument is passed directly to `open(file_path, "rb")` without any path validation. An attacker able to invoke the tool can read arbitrary files readable by the server process and exfiltrate them into a multipart upload directed at an attacker-controlled Confluence host. In the default `streamable-http` transport the server binds `0.0.0.0` with no built-in authentication, making this remotely exploitable without credentials. This is the read-side symmetric twin of GHSA-xjgw-4wvw-rgm4 / CVE-2026-27825 (fixed in v0.17.0). The v0.17.0 patch only covered the download/write path; the upload path that reads local files was left unguarded. Details Vulnerable sink `src/mcp_atlassian/confluence/attachments.py:477` ```python with open(file_path, "rb") as fp: files = {"file": (filename, fp, content_type)} response = self.confluence.session.post(url, files=files, ...) ``` `file_path` is attacker-controlled end-to-end. Taint source `src/mcp_atlassian/servers/confluence.py:1290-1369`, tool definition at `:1307`: ```python file_path: Annotated[str, Field(description="Absolute path to the file to upload")] ``` No Pydantic `pattern=`, no validator, no `validate_safe_path()` call. Call chain 1. MCP client invokes `confluence_upload_attachment(page_id, file_path, ...)` 2. Server handler forwards to `ConfluenceFetcher.upload_attachment(file_path)` 3. `_upload_attachment_direct(file_path)` calls `open(file_path, "rb")` 4. File bytes are streamed in the multipart body of `POST /wiki/rest/api/content/{page_id}/child/attachment` to the configured Confluence base URL — which the attacker also controls (they provided `CONFLUENCE_URL` via env/config or target a server they already control). Asymmetry with the patched download path • `attachments.py:223` (download) — calls `validate_safe_path(local_path)` before `open(..., "wb")` • `attachments.py:272` (download) — calls `validate_safe_path(local_path)` before `open(..., "wb")` • `attachments.py:477` (upload) — no validation The `check_write_access` decorator does not help: it only gates `READ_ONLY_MODE` (default `false`) and is unrelated to filesystem path safety. Default exposure `src/mcp_atlassian/__init__.py:151` and `:360` — default transport is `streamable-http` binding `HOST=0.0.0.0` with no auth layer. Any network-reachable attacker can call MCP tools directly. Severity Primary (default `streamable-http` deployment) • Vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N` • Score: 9.3 Critical • Rationale: network-reachable, unauthenticated, scope-changed because files outside the MCP server's intended resource boundary (Confluence attachments) are exfiltrated. Alternative (stdio-only deployment, conservative) • Vector: `CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N` • Score: 6.6 High • Rationale: local attacker controlling the MCP client context. Maintainer should pick the vector that reflects the documented default deployment. CWE CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') Affected • Product: `sooperset/mcp-atlassian` • Affected versions: >= 0.17.0, <= HEAD (`d8bc78698a63cb6b321c7ca796d6329d448f7f6d`) • Note: v0.17.0 is the fix commit for GHSA-xjgw-4wvw-rgm4 but only addressed the write-side. This read-side twin has existed since that release and remains unpatched on `main`. • Patched versions: none at time of disclosure Proof of Concept Fully reproduced twice end-to-end against a local stdlib HTTP stub acting as the Confluence API, driven by a real MCP stdio client (`mcp.ClientSession` + `stdio_client`) spawning the unmodified `mcp-atlassian` server at HEAD. Permalinks (commit-pinned) • Sink: https://github.com/sooperset/mcp-atlassian/blob/d8bc78698a63cb6b321c7ca796d6329d448f7f6d/src/mcp_atlassian/confluence/attachments.py#L477 • Source (tool def): https://github.com/sooperset/mcp-atlassian/blob/d8bc78698a63cb6b321c7ca796d6329d448f7f6d/src/mcp_atlassian/servers/confluence.py#L1307 • Safe download comparison: https://github.com/sooperset/mcp-atlassian/blob/d8bc78698a63cb6b321c7ca796d6329d448f7f6d/src/mcp_atlassian/confluence/attachments.py#L223 • Default transport bind: https://github.com/sooperset/mcp-atlassian/blob/d8bc78698a63cb6b321c7ca796d6329d448f7f6d/src/mcp_atlassian/__init__.py#L151 Reproduction 1. Start mock Confluence stub: `python mock_confluence.py` (binds `127.0.0.1:8443`, logs all multipart bodies) 2. Launch MCP client against real `mcp-atlassian` server over stdio with `CONFLUENCE_URL=http://127.0.0.1:8443` 3. Call tool: ```json { "name": "confluence_upload_attachment", "arguments": { "page_id": "123456", "file_path": "/etc/passwd", "comment": "poc" } } ``` Run 1 — `/etc/passwd` • MCP response: `isError=False`, `{"message": "Attachment uploaded successfully"}` • Stub captured 3339-byte multipart body containing: `root:x:0:0:root:/root:/bin/bash` (and full passwd contents) Run 2 — `/etc/hostname` • MCP response: `isError=False`, same success envelope • Stub captured 380-byte body containing: `ang3l-pc` Both runs used unmodified server code at commit `d8bc78698a63cb6b321c7ca796d6329d448f7f6d`. PoC artifacts (`mock_confluence.py`, `mcp_client.py`, `poc_run1.sh`, `poc_run2.sh`, `asymmetry.txt`, `ENVIRONMENT.md`) available on request to maintainers via this advisory thread. Impact • Arbitrary file read of anything readable by the server process UID: `/etc/passwd`, `/etc/shadow` (if running as root in container), `~/.aws/credentials`, `~/.ssh/id_rsa`, `.env` files, kube service-account tokens at `/var/run/secrets/kubernetes.io/serviceaccount/token`, application source, database dumps, private keys. • Exfiltration is covert: file bytes transit to the attacker's configured Confluence host inside a normal-looking multipart upload. No error surface; the tool returns success. • In the default `streamable-http` 0.0.0.0 deployment, no credentials are required. • Chains trivially with any AI agent that exposes this MCP server to untrusted prompt input — a prompt-injected assistant can be coerced into calling the tool with a sensitive path. Relationship to GHSA-xjgw-4wvw-rgm4 (CVE-2026-27825) GHSA-xjgw-4wvw-rgm4 (CVSS 9.1, fixed in v0.17.0) addressed an arbitrary file write in the same `attachments.py` module: attacker-controlled paths reaching `open(..., "wb")` on the download side. The fix introduced `validate_safe_path()` and applied it at lines 223 and 272. The upload-side counterpart at line 477 was not updated. Same module, same maintainer, same class of bug (unchecked path → `open()`), opposite direction (read vs write). This advisory reports the incomplete-fix twin. Remediation Required Call `validate_safe_path(file_path)` at the top of `ConfluenceFetcher.upload_attachment` and `_upload_attachment_direct` in `src/mcp_atlassian/confluence/attachments.py`, mirroring the download path at lines 223 and 272. Reject absolute paths outside a configurable allow-listed upload directory and reject any path containing `..` after normalization. Defense in depth Tighten the Pydantic tool schema at `src/mcp_atlassian/servers/confluence.py:1307`: ```python file_path: Annotated[ str, Field( description="Relative path within the configured upload directory", pattern=r"^(?!/)(?!.*\.\.)[\w\-./]+$", ), ] ``` This blocks absolute paths and `..` at the MCP schema layer before the handler is even entered. Additional hardening (out of scope but recommended) • Default `streamable-http` to `127.0.0.1` instead of `0.0.0.0`, or require an auth token when bound to a non-loopback interface. • Document that `file_path` must be confined to an operator-chosen directory and expose that directory via config.

Related

Alias · CVE (1)

  • CVE-2026-77262 MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). vulnerability

Weakness · CWE (1)

  • CWE-22 Improper Limitation of a Pathname to a Restricted Directory weakness

References