Feb 14, 2026·6 min read·28 visits
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.
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 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.
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.
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:
post_id. Even if the admin kicks the unauthorized users from the private channel, that post_id is now known.POST /plugins/jira/api/v2/create-issue?post_id=THE_SECRET_POST_ID HTTP/1.1
Host: mattermost.corp.local
Cookie: MMUSERID=attacker_session"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.
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.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Mattermost Jira Plugin Mattermost | 10.11.0 - 10.11.9 | 10.11.10 |
Mattermost Jira Plugin Mattermost | 11.1.0 - 11.1.2 | 11.1.3 |
Mattermost Jira Plugin Mattermost | < 11.3.0 | 11.3.0 |
| Attribute | Detail |
|---|---|
| CWE | CWE-863 (Incorrect Authorization) |
| CVSS v3.1 | 4.3 (Medium) |
| Attack Vector | Network (Authenticated) |
| Privileges Required | Low (User) |
| EPSS Score | 0.01% (Low) |
| Exploit Status | None (No Public Exploit) |
The software does not perform or incorrectly performs an authorization check when an actor attempts to access a resource or perform an action.
An integer truncation vulnerability (CWE-197) exists in SQLite before version 3.50.2 during the processing of aggregate queries with more than 32,767 distinct column references. This causes an internal 32-bit counter to truncate to a signed 16-bit integer, producing negative values that cause out-of-bounds heap operations in release builds.
An integer overflow vulnerability in the Windows kernel-mode HTTP driver (HTTP.sys) allows an unauthenticated remote attacker to execute arbitrary code with kernel privileges or cause a Denial of Service via a specially crafted sequence of HTTP request headers.
A memory corruption vulnerability exists in the FTS5 (Full-Text Search 5) extension of SQLite prior to version 3.53.2. An attacker can construct a malicious database file containing corrupt FTS5 page data. Querying this database triggers out-of-bounds reads and heap-based buffer overflows, potentially causing a crash or arbitrary code execution.
A mass assignment vulnerability (CWE-915) in n8n's self-service settings API endpoint (PATCH /me/settings) allows authenticated Single Sign-On (SSO) users to disable SSO enforcement for their accounts by injecting administrative parameters. This bypasses organizational identity provider controls and multi-factor authentication (MFA).
CVE-2026-55699 (also identified as GHSA-4gxm-v5v7-fqc4) is a critical path traversal and arbitrary directory deletion vulnerability in the pnpm package manager. The issue exists because the manifest validation process fails to prevent relative path segments within the package 'bin' keys. When a malicious package containing structured path traversal markers is globally installed and later manipulated, pnpm resolves the target paths through path.join() and passes the resolved paths to a recursive deletion function, resulting in arbitrary directory removal.
A path traversal vulnerability in pnpm stage download allows malicious registries or compromised package manifests to overwrite arbitrary files on the victim's filesystem via unvalidated package name and version fields.