Jul 11, 2026·7 min read·33 visits
mcp-atlassian prior to 0.22.0 is vulnerable to directory traversal via the confluence_upload_attachment tool, allowing arbitrary local file exfiltration to Confluence. This can be exploited remotely via indirect prompt injection.
A directory traversal vulnerability exists in the mcp-atlassian integration server prior to version 0.22.0. The confluence_upload_attachment tool fails to restrict the paths of uploaded files, allowing authenticated users or external prompt injection payloads to retrieve and exfiltrate arbitrary files from the server's filesystem into Confluence.
The Model Context Protocol (MCP) is an open standard designed to enable large language model (LLM) agents to interact securely with external tools, APIs, and data sources. The mcp-atlassian package implements this protocol to expose Atlassian Jira and Confluence APIs directly to LLM applications. Among the various tools provided by this server, the confluence_upload_attachment tool is designed to allow agents to upload files from the local filesystem of the hosting machine to a specific page in Confluence.
In versions of mcp-atlassian prior to 0.22.0, the file path supplied to the confluence_upload_attachment tool is processed without any validation against directory boundaries. This omission introduces a directory traversal vulnerability classified under CWE-22, enabling unauthorized access to the host file system. Since the tool executes in the security context of the server process, it can access any file readable by the underlying operating system user.
The exposure is heavily magnified by the typical operating context of LLM agents, which often process untrusted external data. If an agent is directed to read a document containing a malicious payload, an external attacker can execute an Indirect Prompt Injection (IPI) attack. This attack tricks the LLM into calling the vulnerable upload tool with arbitrary file paths, exfiltrating critical system secrets back to the attacker-controlled Confluence space.
The primary defect lies in the path normalization and validation logic within the Confluence attachment component of mcp-atlassian. When a tool call is initiated, the server invokes the upload_attachment method inside src/mcp_atlassian/confluence/attachments.py. This method takes a user-controlled parameter file_path representing the file to be uploaded.
The vulnerable implementation relies solely on os.path.abspath(file_path) to resolve relative paths to absolute paths. While this expansion standardizes the path string, it lacks any boundary checking to verify if the resolved path resides within an approved folder. The code then uses os.path.exists(file_path) to confirm the file is present on disk, which succeeds for any accessible path.
Following this check, the path is forwarded directly to the private helper method _upload_attachment_direct. This method opens the file for reading using the built-in open(file_path, "rb") function without further restriction. The binary content of the file is then wrapped in a standard multipart/form-data request and transmitted to the remote Confluence REST API endpoint. Consequently, any system file that the running process has permission to read can be successfully uploaded and exfiltrated.
A comparative analysis of the codebase reveals the vulnerable path handling versus the corrected validation pattern. In version 0.21.1, the input is processed without strict security controls.
# Vulnerable implementation in v0.21.1
try:
# Convert to absolute path if relative
if not os.path.isabs(file_path):
file_path = os.path.abspath(file_path)
# Check if file exists
if not os.path.exists(file_path):
logger.error(f"File not found: {file_path}")
return {"success": False, "error": f"File not found: {file_path}"}In version 0.22.0, the developer introduced the validate_safe_path utility to restrict the resolution of the file_path parameter to the current working directory.
# Patched implementation in v0.22.0
try:
# Confine the upload source to the workspace before it is read
file_path = str(validate_safe_path(file_path))
# Check if file exists
if not os.path.exists(file_path):
logger.error(f"File not found: {file_path}")
return {"success": False, "error": f"File not found: {file_path}"}The validate_safe_path function, implemented in src/mcp_atlassian/utils/io.py, enforces security boundaries by resolving symlinks and explicitly validating containment. It obtains the absolute path of the base directory (defaulting to the current working directory) using Python's Path.resolve(). It then verifies if the target path is a subpath of the base directory using is_relative_to(). If the validation fails, a ValueError is raised, preventing the file open operation.
# Path validation logic in src/mcp_atlassian/utils/io.py
def validate_safe_path(
path: str | os.PathLike[str],
base_dir: str | os.PathLike[str] | None = None,
) -> Path:
if base_dir is None:
base_dir = os.getcwd()
resolved_base = Path(base_dir).resolve(strict=False)
p = Path(path)
if not p.is_absolute():
p = resolved_base / p
resolved_path = p.resolve(strict=False)
if not resolved_path.is_relative_to(resolved_base):
raise ValueError(
f"Path traversal detected: {path} resolves outside {resolved_base}"
)
return resolved_pathThe patch is robust because it addresses several common bypass techniques. By resolving symlinks using Path.resolve(strict=False), it prevents attackers from using symlink directory traversal to reference files outside the workspace. Furthermore, restricting the default base directory to the current working directory minimizes the exposed attack surface, provided the server process is executed from an isolated, empty directory.
Exploitation can proceed via direct tool invocation or indirect prompt injection. In direct exploitation, an attacker who has authenticated access to the MCP client session issues a request payload targeting sensitive files.
An indirect prompt injection attack requires no credentials and operates through the data ingestion pipeline of the LLM. The attacker places a malicious payload inside an external resource, such as a Jira description or comment, that the agent is scheduled to read.
When the agent processes this content, the instruction-following nature of the LLM is subverted by the injection payload. The LLM interprets the text as a high-priority system command. It then issues an automated tool call to confluence_upload_attachment with the file_path set to a target file such as /proc/self/environ or /etc/passwd.
The host process executes the request autonomously without requiring human authorization. Once the upload completes, the file is available under the page attachments on the targeted Confluence page. The attacker can then view or download the attachment directly, exposing sensitive credentials and system details.
The security consequences of this directory traversal flaw are significant. An attacker can retrieve configuration files, source code, and active process memory data. On Linux systems, reading /proc/self/environ exposes all environment variables of the running shell.
These environment variables typically contain the credentials needed for the mcp-atlassian server to authenticate to the cloud APIs. Specifically, this includes CONFLUENCE_API_TOKEN, JIRA_API_TOKEN, and potentially AWS, GCP, or Azure secret keys used for deployment. Compromise of these tokens allows the attacker to hijack the associated Atlassian workspace accounts, gaining access to confidential corporate databases, wikis, and task trackers.
This vulnerability receives a CVSS score of 7.7. The CVSS vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N reflects the ease of exploitation over the network and the high confidentiality impact. The Scope parameter is marked as Changed (S:C) because the vulnerability on the local server hosting the MCP integration directly leads to data exfiltration and credential exposure on the external Confluence Cloud infrastructure.
Immediate remediation requires upgrading mcp-atlassian to version 0.22.0 or higher. This ensures that all file uploads are restricted to the workspace directory. If an upgrade cannot be performed immediately, several workarounds can help reduce the risk of exploitation.
Deploying the server process with minimal privileges is a key defense. The operating system user running the process should have no read access to sensitive system paths or configuration directories. Additionally, running the process within a sandboxed environment, such as a Docker container with a read-only filesystem, restricts the impact of any file-read capabilities.
Monitoring network traffic and application logs can help detect exploitation attempts. Security teams should analyze Confluence audit logs for unexpected attachment uploads, particularly files originating from system directories or those with unusual extensions. Implementing strict Web Application Firewall (WAF) or network detection rules can block patterns matching directory traversal vectors in API parameters.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
mcp-atlassian sooperset | < 0.22.0 | 0.22.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Network |
| CVSS Score | 7.7 (High) |
| Exploit Status | PoC Available |
| Affected Component | confluence_upload_attachment tool |
| Fixed Version | 0.22.0 |
The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
An uncontrolled resource consumption vulnerability in Strawberry GraphQL allows unauthenticated remote attackers to trigger a Denial of Service on persistent WebSocket connections using the legacy graphql-ws protocol. When the server enforces max_subscriptions_per_connection, naturally terminating subscriptions are not cleared from memory registries, leading to exhaustion of connection slots.
A high-severity type-confusion vulnerability exists in NearForm fast-jwt prior to version 6.3.0. The vulnerability allows attackers to bypass crucial claim validation steps (such as expiration, issuer, audience, and subject validations) by presenting a validly signed JSON Web Token structured as a JSON array instead of a JSON object. This occurs because the library's decoder fails to reject JSON arrays during type evaluation.
NearForm fast-jwt prior to version 6.3.0 is vulnerable to an input validation flaw where configuring verifier properties (such as clockTolerance, clockTimestamp, and cacheTTL) with non-finite values like Infinity or NaN allows attackers to bypass temporal claim validations, including expiration (exp) and activation (nbf) boundaries. This validation bypass can result in unauthorized session persistence and cache poisoning.
A critical cryptographic vulnerability in fast-jwt versions 6.2.x prior to 6.3.0 allows unauthenticated remote attackers to execute an asymmetric-to-symmetric algorithm confusion attack due to incomplete validation of leading non-whitespace prefixes.
CVE-2026-107720 is a critical signature verification bypass vulnerability in NearForm's fast-jwt Node.js library. Under specific configurations where the token verifier is initialized with a falsy cryptographic key (such as an empty string or null) and a non-empty algorithms allowlist, the library erroneously skips signature validation. This allows unauthenticated remote attackers to submit fabricated, unsigned JSON Web Tokens and bypass the authorization boundary of the application entirely.
Ruby Mechanize prior to version 2.14.1 contains an information disclosure vulnerability. When executing cross-origin HTTP redirects, global headers configured on the Mechanize agent (such as Authorization or Session Cookies) are dynamically re-applied to the subsequent request, bypassing the internal header-stripping logic. An attacker who controls a redirection endpoint can capture sensitive bearer tokens or cookies.