GHSA-w66g-j6c4-hcfc CVE-2026-77251 PYSEC-2026-4102
MCP Atlassian: JIRA_PROJECTS_FILTER / CONFLUENCE_SPACES_FILTER allow forbidden-project content exfiltration (one LIVE-proven on Atlassian Cloud)
- Severity
- 0.0 / 10
- Medium ยท CVSS 4.0
- Exploit chance (EPSS)
- 0.27%
- Chance of exploitation in the next 30 days. Higher than 18.52% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- CWE-1276 Hardware Child Block Incorrectly Connected to Parent System
- CWE-184 Incomplete List of Disallowed Inputs
- CWE-693 Protection Mechanism Failure
- CWE-863 Incorrect Authorization
- Fix
0.22.0- Upgrade mcp-atlassian to this version or later
Description
Summary
mcp-atlassian is a popular community MCP server wrapper exposing Jira / Confluence to MCP clients. Operators commonly restrict the surface to a small allowlist of projects/spaces via the JIRA_PROJECTS_FILTER and CONFLUENCE_SPACES_FILTER environment variables, which the README documents as the principal mechanism for limiting attacker-controlled MCP clients (= prompt-injected LLM agents) to the operator's intended subset of the workspace.
We identified three distinct sub-bugs that let attacker-controlled queries read content from forbidden projects/spaces (= projects NOT in the operator's filter) despite the filter being correctly set. The most severe is empirically reproduced on production Atlassian Cloud with real operator credentials and sentinel content in two real projects.
| Sub-bug | Layer | Class | Live? |
|---|---|---|---|
| A1 | Jira jira_search jql |
substring-bypass | ๐ด LIVE PROVEN 2026-05-18 on real Atlassian Cloud |
| A2 | Confluence confluence_search cql |
case-sensitive substring-bypass | code-level verified |
| B | Jira agile get_board_issues / get_agile_boards |
zero-filter (missing check) | code-level verified |
Details
Sub-bug A1 โ src/mcp_atlassian/jira/search.py lines 92-94 at HEAD d8bc78698a63cb6b321c7ca796d6329d448f7f6d:
if projects_filter and "project = " not in jql.lower():
jql = f"{jql} AND project in ({','.join(projects_filter)})"
The substring check is satisfied by any JQL of the form project = <forbidden-project> โ including a project NOT in projects_filter. The wrapper does NOT verify that the project named in the user JQL is a member of the allowlist. The user-supplied JQL is sent verbatim to Jira's search API which returns content from the forbidden project (Jira's authorization is satisfied because the operator's PAT typically has broader access than the operator's intended allowlist โ which is why the operator set a filter in the first place).
Sub-bug A2 โ src/mcp_atlassian/confluence/search.py line 60: same pattern as A1, PLUS the substring check "space = " not in cql is case-sensitive (no .lower()). User CQL SPACE = "<forbidden-space>" (uppercase) bypasses the substring match.
Sub-bug B โ get_board_issues and get_agile_boards paths have no projects_filter enforcement at all โ no substring check, no AST walk, the allowlist is silently ignored. An MCP client invoking get_agile_boards enumerates boards across the entire workspace (including forbidden projects), and get_board_issues(boardId=<forbidden-board>) returns all issues with no filter check.
PoC
End-to-end Phase C against real Atlassian Cloud + real mcp-atlassian Python binary v0.21.1 (latest on PyPI) with operator-provided test workspace and two real Jira projects (one allowed, one forbidden via JIRA_PROJECTS_FILTER):
| Step | JQL submitted | Result | Verdict |
|---|---|---|---|
| 1 initialize | โ | MCP 2024-11-05 OK | โ |
| 2 tools/list | โ | 33+ tools incl. jira_search |
โ |
| 3 CONTROL | project = <allowed> |
returns allowed issue | โ |
| 4 NEG CTRL | summary ~ "any-string" |
wrapper appends AND project in (<allowed>) โ 0 forbidden results |
โ |
| 5 BYPASS A1 | project = <forbidden> |
returns forbidden issue with sentinel content | ๐ด BYPASS |
Full RPC log and a reproducible test script are available in a disclosure bundle I have prepared. I can share the zip via a private channel (email / your preferred private fork / encrypted upload) โ please reply with your preference. The bundle includes:
- 00-FINDING-REPORT.md (primary report)
- ATTACK-MATRIX.md
- Verbatim source files at HEAD with sha256 chain of custody (
source-jira-search.py,source-confluence-search.py) - Phase C live test script + JSON-RPC witness log
- Bundle zip sha256:
034cbf0bcb66c325be9373ff2dc186b8b0e1747c5165d6fba3bca83054949dd3
Repro recipe (no bundle needed) :
pip install mcp-atlassian
export JIRA_URL=https://<your-test-workspace>.atlassian.net
export JIRA_USERNAME=<your-test-email>
export JIRA_API_TOKEN=<your-pat>
export JIRA_PROJECTS_FILTER=<your-allowed-project-key>
# Then drive the MCP via stdio JSON-RPC with tools/call jira_search jql="project = <forbidden-project-key>"
# Expect: forbidden project content returned despite the filter.
Impact
Severity is higher in deployments where the operator's PAT covers a broader set of projects than JIRA_PROJECTS_FILTER (= the common configuration, which is the reason operators set the filter).
Affected: every operator who relies on JIRA_PROJECTS_FILTER / CONFLUENCE_SPACES_FILTER to confine an attacker-controlled MCP client (= prompt-injected LLM agent) to a subset of their workspace.
Suggested fix
- Replace substring checks with AST-based JQL/CQL parsers that walk the WHERE clause looking for
project/spaceconstraints. Reject queries whoseproject/spaceconstraint references a key not in the allowlist. - Add
projects_filtercheck insideget_board_issues(resolve board โ project, reject if not in filter) andget_agile_boards(filter returned list). - Make the Confluence substring check case-insensitive (
cql.lower()) for defense-in-depth, even after the AST fix lands. - Default-deny for ambiguous queries: if the AST parser can't fully classify a clause, refuse instead of pass-through.
- Add unit tests that assert attacker JQL
project = <not-in-filter>returns zero results when the filter is set.
Disclosure
ISO/IEC 29147. Default 90-day embargo from the date you acknowledge receipt. Happy to coordinate the CVE via the GitHub CNA pipeline. Credit under: Mordehai Attia, Founder, Corsen AI (https://corsen.ai , GitHub @CorsenAI).
Thank you for maintaining mcp-atlassian โ the project is widely used and your security policy was clear, which made this disclosure straightforward to file. Looking forward to coordinating the fix.
Affected versions
PyPI
| Package | Vulnerable | Fixed in |
|---|---|---|
| mcp-atlassian | < 0.22.0 |
0.22.0 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
mcp-atlassian PyPI โ 0.22.0
- pip
pip install --upgrade "mcp-atlassian>=0.22.0"- poetry
poetry add "mcp-atlassian>=0.22.0"- uv
uv add "mcp-atlassian>=0.22.0"
Severity breakdown
CVSS 4.0 0.0
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
- Attack vector
- Network
- Attack complexity
- Low
- Attack requirements
- None
- Privileges required
- Low
- User interaction
- None
- Confidentiality (vulnerable system)
- High
- Integrity (vulnerable system)
- None
- Availability (vulnerable system)
- None
- Confidentiality (subsequent systems)
- High
- Integrity (subsequent systems)
- None
- Availability (subsequent systems)
- None
CVSS 3.1 6.5
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- Low
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Weakness
CWE-1276: Hardware Child Block Incorrectly Connected to Parent System
Signals between a hardware IP and the parent system design are incorrectly connected causing security risks.
How to prevent it
- Testing: System-level verification may be used to ensure that components are correctly connected and that design security requirements are not violated due to interactions between various IP blocks.
CWE-184: Incomplete List of Disallowed Inputs
The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are not allowed by policy or otherwise require other action to neutralize before additional processing takes place, but the list is incomplete.
How to prevent it
- Implementation: Do not rely exclusively on detecting disallowed inputs. There are too many variants to encode a character, especially when different environments are used, so there is a high likelihood of missing some variants. Only use detection of disallowed inputs as a mechanism for detecting suspicious activity. Ensure that you are using other protection mechanisms that only identify "good" input - such as lists of allowed inputs - and ensure that you are properly encoding your outputs.
CWE-693: Protection Mechanism Failure
The product does not use or incorrectly uses a protection mechanism that provides sufficient defense against directed attacks against the product.
CWE-863: Incorrect Authorization
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
How to prevent it
- Architecture and Design: Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries. Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
- Architecture and Design: Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
- Architecture and Design: Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid. For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
- Architecture and Design: For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page. One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
- System Configuration, Installation: Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.
References
Advisories
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-g2r2-3j32-j27x MCP Atlassian: Reflected XSS in OAuth Setup Callback Handler | Medium | Also affects mcp-atlassian |
| GHSA-h7wj-5v37-59r2 MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read (incomplete fix for CVE-2026-27825) | Medium | Also affects mcp-atlassian |
| GHSA-4596-2p6p-28cv MCP Atlassian: Insecure File Permissions on OAuth Token Storage | Medium | Also affects mcp-atlassian |
| GHSA-mfv2-4wvm-9pgp MCP Atlassian: Path traversal in upload_attachment allows arbitrary file read and exfiltration via MCP tool call | Medium | Also affects mcp-atlassian |
| GHSA-p6hp-93wp-fh6p MCP Atlassian: Path Traversal / Arbitrary File Read in confluence_upload_attachment MCP tool (incomplete fix of GHSA-xjgw-4wvw-rgm4) | High | Also affects mcp-atlassian |
| GHSA-6cr4-ccf3-x7h4 MCP Atlassian: Arbitrary file read via confluence_upload_attachment allows exfiltration of server credentials | High | Also affects mcp-atlassian |
| GHSA-mrq8-fv7v-hhjg MCP Atlassian: HTTP upload tools accept arbitrary server-local file paths | Medium | Also affects mcp-atlassian |
| GHSA-2xj6-xx86-cwwc MCP Atlassian: Arbitrary File Read & Exfiltration (Confused Deputy) in JIRA update_issue | High | Also affects mcp-atlassian |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor