PYSEC-2026-4089
Vulnerability from pysec - Published: 2026-10-01 16:38 - Updated: 2026-10-01 17:10Summary
In the documented multi-user HTTP deployment (--transport streamable-http with global operator Atlassian credentials), sooperset/mcp-atlassian exposes all tools to unauthenticated network clients, and the upload_attachment tool reads an attacker-supplied file_path with no path validation. Chained, an unauthenticated network attacker reads arbitrary files on the MCP server host (e.g. /proc/self/environ → the operator's Atlassian API token + .env secrets, ~/.ssh/id_rsa, /etc/passwd) by uploading them to an attacker-chosen page/issue and reading them back.
Details
Missing authentication (transport):
- streamable-http binds 0.0.0.0 by default (src/mcp_atlassian/__init__.py:151).
- The OAuth-proxy auth provider is opt-in (ATLASSIAN_OAUTH_PROXY_ENABLE, default false), so main_mcp is built with auth=None (src/mcp_atlassian/servers/main.py:724-731, 813-817).
- UserTokenMiddleware._parse_auth_header sets auth_validation_error only for a malformed Authorization header; a request with no Authorization header passes through (main.py:416-446, 582-595).
- _get_fetcher then falls through to the global credential fallback using the operator's .env Atlassian token (src/mcp_atlassian/servers/dependencies.py:644-676). check_write_access gates only on read-only mode, not auth → read and write tools reachable.
Arbitrary file read (sink):
- upload_attachment's file_path flows unsanitized into open(file_path, 'rb') — Confluence src/mcp_atlassian/confluence/attachments.py:477 (from servers/confluence.py:1294-1369); Jira src/mcp_atlassian/jira/attachments.py:386 (from servers/jira.py:1609-1673). No validate_safe_path / allowlist (contrast the download flow, hardened after CVE-2026-27825).
Proof of Concept
# unauthenticated (no Authorization header) against a default streamable-http deployment:
tools/call upload_attachment { "file_path": "/proc/self/environ", "page_id": "<attacker-chosen>" }
# then read it back:
tools/call download_attachment { ... } # returns the bytes (base64) -> operator's ATLASSIAN token + .env secrets
Impact
Unauthenticated arbitrary local file read on the MCP server host — including the operator's Atlassian API token and .env secrets — a boundary the Atlassian-scoped tool must not cross, plus unauthenticated use of every read/write Atlassian tool as the operator's (often admin) principal. Distinct from GHSA-xjgw-4wvw-rgm4 (file write via download_path) and GHSA-7r34-79r5-rcc9 (URL-header SSRF).
Suggested fix
Require authentication on the streamable-http transport by default (do not fall back to operator global credentials for unauthenticated requests); apply validate_safe_path/allowlist to file_path in upload_attachment as the download flow already does.
Affected
mcp-atlassian <= 0.21.1.
| Name | purl | mcp-atlassian | pkg:pypi/mcp-atlassian |
|---|
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "mcp-atlassian",
"purl": "pkg:pypi/mcp-atlassian"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.22.0"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.1.1",
"0.1.10",
"0.1.11",
"0.1.12",
"0.1.13",
"0.1.14",
"0.1.15",
"0.1.16",
"0.1.2",
"0.1.3",
"0.1.4",
"0.1.6",
"0.1.7",
"0.1.8",
"0.1.9",
"0.10.0",
"0.10.1",
"0.10.2",
"0.10.3",
"0.10.4",
"0.10.5",
"0.10.6",
"0.11.0",
"0.11.1",
"0.11.10",
"0.11.11",
"0.11.12",
"0.11.2",
"0.11.2a2",
"0.11.3",
"0.11.4",
"0.11.5",
"0.11.6",
"0.11.7",
"0.11.8",
"0.11.9",
"0.12.0",
"0.13.0",
"0.13.1",
"0.14.0",
"0.14.1",
"0.14.2",
"0.14.3",
"0.15.0",
"0.16.0",
"0.16.1",
"0.17.0",
"0.18.0",
"0.18.1",
"0.19.0",
"0.2.0",
"0.2.1",
"0.2.2",
"0.2.3",
"0.2.4",
"0.2.5",
"0.2.6",
"0.20.0",
"0.20.1",
"0.21.0",
"0.21.1",
"0.3.0",
"0.3.1",
"0.4.0",
"0.5.0",
"0.6.0",
"0.6.1",
"0.6.2",
"0.6.3",
"0.6.4",
"0.6.5",
"0.7.0",
"0.7.1",
"0.8.0",
"0.8.1",
"0.8.2",
"0.8.3",
"0.8.4",
"0.9.0"
]
}
],
"aliases": [
"CVE-2026-77248",
"GHSA-cc5h-2pwp-pvcc"
],
"details": "### Summary\nIn the documented multi-user HTTP deployment (`--transport streamable-http` with global operator Atlassian credentials), sooperset/mcp-atlassian exposes all tools to **unauthenticated network clients**, and the `upload_attachment` tool reads an attacker-supplied `file_path` with **no path validation**. Chained, an unauthenticated network attacker reads arbitrary files on the MCP server host (e.g. `/proc/self/environ` \u2192 the operator\u0027s Atlassian API token + `.env` secrets, `~/.ssh/id_rsa`, `/etc/passwd`) by uploading them to an attacker-chosen page/issue and reading them back.\n\n### Details\n**Missing authentication (transport):**\n- streamable-http binds `0.0.0.0` by default (`src/mcp_atlassian/__init__.py:151`).\n- The OAuth-proxy auth provider is opt-in (`ATLASSIAN_OAUTH_PROXY_ENABLE`, default false), so `main_mcp` is built with `auth=None` (`src/mcp_atlassian/servers/main.py:724-731, 813-817`).\n- `UserTokenMiddleware._parse_auth_header` sets `auth_validation_error` only for a *malformed* Authorization header; a request with **no** Authorization header passes through (`main.py:416-446, 582-595`).\n- `_get_fetcher` then falls through to the global credential fallback using the operator\u0027s `.env` Atlassian token (`src/mcp_atlassian/servers/dependencies.py:644-676`). `check_write_access` gates only on read-only mode, not auth \u2192 read **and** write tools reachable.\n\n**Arbitrary file read (sink):**\n- `upload_attachment`\u0027s `file_path` flows unsanitized into `open(file_path, \u0027rb\u0027)` \u2014 Confluence `src/mcp_atlassian/confluence/attachments.py:477` (from `servers/confluence.py:1294-1369`); Jira `src/mcp_atlassian/jira/attachments.py:386` (from `servers/jira.py:1609-1673`). No `validate_safe_path` / allowlist (contrast the download flow, hardened after CVE-2026-27825).\n\n### Proof of Concept\n```\n# unauthenticated (no Authorization header) against a default streamable-http deployment:\ntools/call upload_attachment { \"file_path\": \"/proc/self/environ\", \"page_id\": \"\u003cattacker-chosen\u003e\" }\n# then read it back:\ntools/call download_attachment { ... } # returns the bytes (base64) -\u003e operator\u0027s ATLASSIAN token + .env secrets\n```\n\n### Impact\nUnauthenticated arbitrary local file read on the MCP server host \u2014 including the operator\u0027s Atlassian API token and `.env` secrets \u2014 a boundary the Atlassian-scoped tool must not cross, plus unauthenticated use of every read/write Atlassian tool as the operator\u0027s (often admin) principal. Distinct from GHSA-xjgw-4wvw-rgm4 (file *write* via download_path) and GHSA-7r34-79r5-rcc9 (URL-header SSRF). \n\n### Suggested fix\nRequire authentication on the streamable-http transport by default (do not fall back to operator global credentials for unauthenticated requests); apply `validate_safe_path`/allowlist to `file_path` in `upload_attachment` as the download flow already does.\n\n### Affected\n`mcp-atlassian` \u003c= 0.21.1.",
"id": "PYSEC-2026-4089",
"modified": "2026-10-01T17:10:30.459484Z",
"published": "2026-10-01T16:38:34.842921Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sooperset/mcp-atlassian/security/advisories/GHSA-cc5h-2pwp-pvcc"
},
{
"type": "WEB",
"url": "https://github.com/sooperset/mcp-atlassian/pull/1448"
},
{
"type": "WEB",
"url": "https://github.com/sooperset/mcp-atlassian/commit/b041733473f95119dd539542a43c280737a8e460"
},
{
"type": "PACKAGE",
"url": "https://github.com/sooperset/mcp-atlassian"
},
{
"type": "WEB",
"url": "https://github.com/sooperset/mcp-atlassian/releases/tag/v0.22.0"
},
{
"type": "PACKAGE",
"url": "https://pypi.org/project/mcp-atlassian"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-cc5h-2pwp-pvcc"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-77248"
}
],
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "MCP Atlassian: Unauthenticated arbitrary local file read via upload_attachment file_path, chained with missing auth on streamable-http transport"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.