VYPR
Medium severity4.3NVD Advisory· Published May 18, 2026· Updated May 18, 2026

CVE-2026-6339

CVE-2026-6339

Description

Mattermost versions 11.5.x <= 11.5.1, 11.4.x <= 11.4.3 fail to validate the X-Requested-With header on the burn-on-read reveal endpoint which allows an authenticated channel member to force the reveal of a burn-on-read message without recipient consent via a crafted Markdown image tag.. Mattermost Advisory ID: MMSA-2026-00636

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Mattermost fails to validate the X-Requested-With header on the burn-on-read reveal endpoint, allowing an attacker to force a message reveal via a crafted Markdown image tag.

Vulnerability

Mattermost versions 11.5.x up to and including 11.5.1, and 11.4.x up to and including 11.4.3 fail to validate the X-Requested-With header on the burn-on-read reveal endpoint. This allows an authenticated channel member to force the reveal of a burn-on-read message without the recipient's consent by embedding a crafted Markdown image tag that triggers a cross-site request forgery (CSRF) style action [1].

Exploitation

An attacker who is an authenticated member of the target channel can craft a Markdown image tag pointing to the burn-on-read reveal endpoint with the appropriate parameters. When a recipient views the message containing this image tag, the recipient's browser automatically sends a request to that endpoint, revealing the burn-on-read content without the recipient's explicit action. The attacker does not require the recipient to click a link; viewing the message is sufficient [1].

Impact

Successful exploitation bypasses the intended consent mechanism for burn-on-read messages. The attacker gains the ability to read the content of a burn-on-read message that would otherwise require the recipient to manually click to reveal. This is a violation of the expected confidentiality controls for such messages [1].

Mitigation

Mattermost has released security updates to address this vulnerability. Users should upgrade to Mattermost version 11.5.2, 11.4.4, or later as per the advisory MMSA-2026-00636 [1]. No workaround has been documented; applying the fix is the recommended action.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

1
b6a14e162c9c

MM-68001 - enforce X-Requested-With header validation on BoR reveal endpoint (#35793) (#35826)

https://github.com/mattermost/mattermostMattermost BuildMar 27, 2026Fixed in 11.4.4via llm-release-walk
3 files changed · +59 0
  • server/channels/api4/post.go+9 0 modified
    @@ -1491,6 +1491,15 @@ func rewriteMessage(c *Context, w http.ResponseWriter, r *http.Request) {
     }
     
     func revealPost(c *Context, w http.ResponseWriter, r *http.Request) {
    +	// Enforce X-Requested-With header for cookie-authenticated requests.
    +	if r.Header.Get(model.HeaderAuth) == "" {
    +		if r.Header.Get(model.HeaderRequestedWith) != model.HeaderRequestedWithXML {
    +			c.Err = model.NewAppError("revealPost", "api.post.reveal_post.invalid_request.app_error",
    +				nil, "missing or invalid X-Requested-With header", http.StatusForbidden)
    +			return
    +		}
    +	}
    +
     	c.RequirePostId()
     	if c.Err != nil {
     		return
    
  • server/channels/api4/post_test.go+46 0 modified
    @@ -5894,6 +5894,52 @@ func TestRevealPost(t *testing.T) {
     		CheckForbiddenStatus(t, resp)
     		require.Nil(t, revealedPost)
     	}, "user without channel access")
    +
    +	t.Run("cookie auth without X-Requested-With header should be rejected", func(t *testing.T) {
    +		enableBurnOnReadFeature(th)
    +
    +		_, client2 := createSecondUser(th.BasicChannel)
    +		post := createBurnOnReadPost(client2, th.BasicChannel)
    +
    +		// Build a raw HTTP request using cookie-based auth (no Authorization header)
    +		// and without the X-Requested-With header — simulating a passive resource load
    +		revealURL := th.Client.APIURL + "/posts/" + post.Id + "/reveal"
    +		req, err := http.NewRequest("GET", revealURL, nil)
    +		require.NoError(t, err)
    +
    +		req.AddCookie(&http.Cookie{
    +			Name:  model.SessionCookieToken,
    +			Value: th.Client.AuthToken,
    +		})
    +
    +		resp, err := th.Client.HTTPClient.Do(req)
    +		require.NoError(t, err)
    +		defer resp.Body.Close()
    +		require.Equal(t, http.StatusForbidden, resp.StatusCode)
    +	})
    +
    +	t.Run("cookie auth with X-Requested-With header should be accepted", func(t *testing.T) {
    +		enableBurnOnReadFeature(th)
    +
    +		_, client2 := createSecondUser(th.BasicChannel)
    +		post := createBurnOnReadPost(client2, th.BasicChannel)
    +
    +		// Build a raw HTTP request using cookie-based auth with the X-Requested-With header
    +		revealURL := th.Client.APIURL + "/posts/" + post.Id + "/reveal"
    +		req, err := http.NewRequest("GET", revealURL, nil)
    +		require.NoError(t, err)
    +
    +		req.AddCookie(&http.Cookie{
    +			Name:  model.SessionCookieToken,
    +			Value: th.Client.AuthToken,
    +		})
    +		req.Header.Set(model.HeaderRequestedWith, model.HeaderRequestedWithXML)
    +
    +		resp, err := th.Client.HTTPClient.Do(req)
    +		require.NoError(t, err)
    +		defer resp.Body.Close()
    +		require.Equal(t, http.StatusOK, resp.StatusCode)
    +	})
     }
     
     func TestCreateBurnOnReadPost(t *testing.T) {
    
  • server/i18n/en.json+4 0 modified
    @@ -2862,6 +2862,10 @@
         "id": "api.post.reveal_post.disabled.app_error",
         "translation": "Burn-on-read feature is not enabled or requires an Enterprise Advanced license."
       },
    +  {
    +    "id": "api.post.reveal_post.invalid_request.app_error",
    +    "translation": "Invalid request: missing or invalid X-Requested-With header."
    +  },
       {
         "id": "api.post.reveal_post.user_not_in_channel.app_error",
         "translation": "You do not have permission to reveal this post. You must be a member of the channel."
    

Vulnerability mechanics

Root cause

"Missing validation of the X-Requested-With header on the burn-on-read reveal endpoint allows cross-origin requests to force message reveal without recipient consent."

Attack vector

An authenticated channel member crafts a Markdown image tag pointing to the burn-on-read reveal endpoint (e.g., `![img](https://mattermost.example.com/api/v4/posts/{postId}/reveal)`). When another channel member views the message containing this tag, the browser automatically issues a GET request to that URL, including any cookies for the Mattermost origin. Because the reveal endpoint previously did not require the `X-Requested-With` header [CWE-346], the server treats this passive resource load as a legitimate reveal request, triggering the burn-on-read action without the recipient's knowledge or consent.

Affected code

The vulnerable code is in `server/channels/api4/post.go` in the `revealPost` function. The endpoint at `POST /api/v4/posts/{post_id}/reveal` lacked any check for the `X-Requested-With` header, allowing cookie-authenticated cross-origin requests to trigger the burn-on-read reveal.

What the fix does

The patch adds a guard at the top of `revealPost` in `server/channels/api4/post.go` [patch_id=918515] that checks whether the request carries an `Authorization` header. If not (meaning the request relies on cookie-based authentication), the server now requires the `X-Requested-With` header to be set to `XMLHttpRequest`. Requests without this header are rejected with HTTP 403. This prevents browsers from treating the reveal endpoint as a simple cross-origin resource load, since the `X-Requested-With` header cannot be set by a standard `<img>` tag or other passive HTML elements. The corresponding test cases in `post_test.go` confirm that cookie-authenticated requests without the header are rejected while those with the header succeed.

Preconditions

  • authAttacker must be an authenticated member of the target channel
  • configBurn-on-read feature must be enabled on the Mattermost server
  • inputTarget recipient must view a message containing the crafted Markdown image tag
  • inputAttacker must know the post ID of a burn-on-read message

Generated on May 20, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

1

News mentions

0

No linked articles in our index yet.