Vendor toolingHighSecurity exploitPrompt injection

MCP Atlassian server lets prompt-injected agent exfiltrate arbitrary local files via upload_attachment

Undisclosed·mcp-atlassian (MCP server for Jira/Confluence, used as a tool by LLM agents)Fixed

The Confluence and Jira upload_attachment tool paths in mcp-atlassian took a caller-supplied file_path and opened it directly for upload after only calling os.path.abspath(), with no check that the path stayed inside an allowed directory; an attacker could plant an instruction in a Jira issue or Confluence page (e.g. 'file_path: /home/mcp-user/.ssh/id_rsa') that a connected LLM agent would read and then invoke as a tool call, causing the server to read that local file and upload it as an attachment to an attacker-controlled page. The same primitive was also reachable pre-auth over the streamable-http transport when bound non-loopback, using the operator's global Atlassian credentials with no prompt injection needed.

Blast radius
Arbitrary local files readable by the MCP server process — SSH private keys, .env files, cloud credential files, /etc/passwd — could be exfiltrated by uploading them as attachments to an attacker-accessible Jira/Confluence location; scope limited to deployments running mcp-atlassian versions before 0.22.0. No specific victim organisation, data volume, or in-the-wild exploitation was disclosed in the advisory.
Root cause
The write-direction path traversal (CVE-2026-27825) was patched with validate_safe_path() on download/write paths, but the symmetric upload/read code path in confluence/attachments.py and jira/attachments.py was never updated to apply the same confinement check, leaving os.path.abspath() as the only guard — which restricts nothing.
How it was caught
Found and reported by an external security researcher (Sean Valentine) via responsible disclosure to the maintainer, not discovered through production monitoring or an actual exploitation incident.
What changed
Fixed in mcp-atlassian v0.22.0: upload_attachment and content_file paths now go through validate_safe_path() so caller-supplied paths must resolve inside the server's working directory, and the streamable-http transport no longer falls back to the operator's global credentials for unauthenticated requests (opt-in only via ALLOW_GLOBAL_CRED_FALLBACK, default off, with 401 rejection otherwise).

Take-awayAny file-path parameter an LLM agent can populate from untrusted content (issue text, page content) needs the same directory-confinement check on every code path that touches the filesystem, not just the one direction that was previously exploited.

First surfaced: Security advisory · Recorded