CVE-2026-22892

Confused Deputy in the Chatroom: Dissecting CVE-2026-22892

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 14, 2026·6 min read·2 visits

Executive Summary (TL;DR)

The Mattermost Jira Plugin failed to verify user permissions when creating Jira issues from Mattermost posts. An attacker with a valid Post ID can force the plugin to retrieve and display content from private channels they cannot access. Fixed in version 11.3.0 and patch releases.

Mattermost is the fortress of secure collaboration, and Jira is the labyrinth of project management. When you bridge the two, you expect a secure tunnel, not a porous sieve. CVE-2026-22892 is a classic authorization bypass within the Mattermost Jira Plugin that allows users to peek into channels they don't belong to. By exploiting a missing permission check in the issue creation workflow, an authenticated user can retrieve post content and attachments from private channels—provided they can guess or acquire the target Post ID. It's a textbook case of the 'Confused Deputy' problem, where a privileged plugin unwittingly does the dirty work for an unprivileged user.

The Hook: When ChatOps Goes Rogue

We all love ChatOps. The idea that you can create a Jira ticket directly from a Mattermost rant is the peak of developer efficiency. You see a bug reported in the #ops-nightmare channel, you click a button, and boom—it's in the backlog. It’s seamless. It’s productive. And apparently, it was a little too open.

Enter the Mattermost Jira Plugin. Like most plugins in the Mattermost ecosystem, it acts as a bridge between the chat server and external services. To do its job, the plugin needs to read messages, grab attachments, and format them for Jira. The problem arises when the plugin forgets who it's working for. It runs with system-level privileges to fetch data, but it interacts with users who definitely do not have system-level privileges.

CVE-2026-22892 is the story of what happens when that bridge assumes that just because you asked to cross, you're allowed to cross. It’s a classic failure to validate the authorization context, turning a productivity feature into a potential peep-hole for internal snoops.

The Flaw: The Confused Deputy

The vulnerability lies in the /create-issue API endpoint. When a user decides to turn a message into a Jira issue, the frontend sends a request to the plugin backend containing the post_id of the message. The plugin's job is to fetch that message, extract the text and any file attachments, and present a modal to the user so they can finalize the Jira ticket.

Here is where the logic went off the rails. The plugin utilized its own elevated service privileges to query the Mattermost database for the post_id. The database, recognizing the plugin as a trusted entity, happily handed over the data—regardless of whether the post was in a public channel, a private group, or a direct message between the CEO and the Lawyer.

The plugin then took this sensitive data and returned it to the requesting user's browser to populate the 'Create Issue' form. The missing step? Checking if the requesting user actually had read access to the channel where post_id lived. The plugin acted as a 'Confused Deputy'—a privileged entity tricked into misusing its authority to serve an unauthorized request.

The Code: Missing the Guardrails

Let's look at the logic flow. In the vulnerable version, the handler for creating an issue looked something like this (simplified for dramatic effect):

// VULNERABLE LOGIC
func (p *Plugin) handleCreateIssue(w http.ResponseWriter, r *http.Request) {
    // 1. Get the target Post ID from the request
    postID := r.URL.Query().Get("post_id")
    
    // 2. Fetch the post using the Plugin's API interface
    // Note: This often bypasses user-level checks if not scoped correctly
    post, err := p.API.GetPost(postID)
    if err != nil {
        http.Error(w, "Post not found", 404)
        return
    }
 
    // 3. Return the post content to the user so they can edit the Jira ticket
    // OOPS: We never checked if 'r.Header.Get("Mattermost-User-ID")' is allowed to see 'post'
    json.NewEncoder(w).Encode(post)
}

The fix, applied in commit 99ffe20, introduces a mandatory permission check before returning any data. It explicitly verifies that the user making the request has ReadChannel permissions for the channel the post resides in.

// PATCHED LOGIC
func (p *Plugin) handleCreateIssue(w http.ResponseWriter, r *http.Request) {
    postID := r.URL.Query().Get("post_id")
    userID := r.Header.Get("Mattermost-User-ID") // The actual human
 
    // 1. Fetch the post
    post, err := p.API.GetPost(postID)
    if err != nil { ... }
 
    // 2. THE FIX: Check permissions explicitly
    // Does 'userID' have permission to read 'post.ChannelId'?
    if !p.API.HasPermissionToChannel(userID, post.ChannelId, model.PERMISSION_READ_CHANNEL) {
        http.Error(w, "Forbidden: You cannot access this post", 403)
        return
    }
 
    // 3. Proceed only if authorized
    json.NewEncoder(w).Encode(post)
}

It’s a subtle change—just a few lines of code—but it marks the difference between a secure application and a data leak.

The Exploit: Guessing Games

Exploiting this isn't as simple as incrementing an ID counter (thankfully, Mattermost uses 26-character alphanumeric KSUID-style IDs, not integers). You can't just loop from id=1 to id=1000. However, 'Security by Obscurity' is not a valid defense.

The Attack Scenario:

  1. The Leaked Link: Imagine a scenario where a link to a sensitive post in a private channel was shared in a public channel by mistake. The link contains the post_id. Even if the admin kicks the unauthorized users from the private channel, that post_id is now known.
  2. The Request: The attacker, authenticated but unauthorized for the target channel, constructs a raw HTTP request to the plugin endpoint:
    POST /plugins/jira/api/v2/create-issue?post_id=THE_SECRET_POST_ID HTTP/1.1
    Host: mattermost.corp.local
    Cookie: MMUSERID=attacker_session
  3. The Response: The server replies with JSON containing the message text ("Simpsons, we need to talk about the layoffs...") and links to file attachments.

While the CVSS score is a modest 4.3 due to the difficulty of obtaining that ID, the impact if an ID is known is total confidentiality loss for that specific message. This is particularly dangerous for 'Insider Threat' scenarios where a user might have retained IDs from a channel they were recently removed from.

The Impact: Small Leak, Big Problems

Why does a 4.3 Medium severity matter? Because context is king. In corporate environments, Mattermost is often the repository of the most sensitive, ephemeral data: credentials pasted in haste, HR discussions about terminations, or legal strategies.

If an attacker (perhaps a disgruntled employee) has access to a log file, a screenshot, or a browser history that reveals the post_id of a sensitive discussion, this vulnerability allows them to bypass the channel membership restrictions entirely. They don't need to be in the room to hear the conversation; they just need to know the room number.

Furthermore, this bypasses the fundamental promise of 'Private' channels. It erodes trust in the platform. If a user is removed from a channel, they expect their access to cease immediately. This vulnerability allowed a 'zombie' access pattern where knowledge of the metadata (the ID) granted access to the data.

Fix Analysis (1)

Technical Appendix

CVSS Score
4.3/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
EPSS Probability
0.01%
Top 90% most exploited

Affected Systems

Mattermost Server (Jira Plugin) 10.11.x < 10.11.10Mattermost Server (Jira Plugin) 11.1.x < 11.1.3Mattermost Server (Jira Plugin) 11.2.x < 11.2.2Mattermost Server (Jira Plugin) < 11.3.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
Mattermost Jira Plugin
Mattermost
10.11.0 - 10.11.910.11.10
Mattermost Jira Plugin
Mattermost
11.1.0 - 11.1.211.1.3
Mattermost Jira Plugin
Mattermost
< 11.3.011.3.0
AttributeDetail
CWECWE-863 (Incorrect Authorization)
CVSS v3.14.3 (Medium)
Attack VectorNetwork (Authenticated)
Privileges RequiredLow (User)
EPSS Score0.01% (Low)
Exploit StatusNone (No Public Exploit)
CWE-863
Incorrect Authorization

The software does not perform or incorrectly performs an authorization check when an actor attempts to access a resource or perform an action.

Vulnerability Timeline

CVE Published
2026-02-13
Patch Committed (PR #1236)
2026-02-05
Advisory MMSA-2025-00550 Released
2026-02-13