Moderate severityNVD Advisory· Published Apr 14, 2025· Updated Apr 14, 2025
Unauthorized Bot Login Using Credentials
CVE-2025-2475
Description
Mattermost versions 10.5.x <= 10.5.1, 10.4.x <= 10.4.3, 9.11.x <= 9.11.9 fail to invalidate the cache when a user account is converted to a bot which allows an attacker to login to the bot exactly one time via normal credentials.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/mattermost/mattermost/server/v8Go | >= 10.5.0, < 10.5.2 | 10.5.2 |
github.com/mattermost/mattermost/server/v8Go | >= 9.11.0, < 9.11.10 | 9.11.10 |
github.com/mattermost/mattermost/server/v8Go | < 8.0.0-20250220161544-fd356b62b4dd | 8.0.0-20250220161544-fd356b62b4dd |
Affected products
1- Range: 10.5.0
Patches
540fd60714bd0[Cherry-pick][AI assisted] MM-62837: (#30268) (#30296)
2 files changed · +21 −0
server/channels/api4/user_test.go+19 −0 modified@@ -6641,6 +6641,25 @@ func TestConvertUserToBot(t *testing.T) { require.NoError(t, err) require.NotNil(t, bot) }) + + t.Run("user cannot login after being converted to bot", func(t *testing.T) { + // Create a new user + user := th.CreateUser() + + // Login as the new user to verify login works initially + _, _, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.NoError(t, err) + + // Convert user to bot + _, _, err = th.SystemAdminClient.ConvertUserToBot(context.Background(), user.Id) + require.NoError(t, err) + + // Try to login again - should fail + _, resp, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.Error(t, err) + CheckErrorID(t, err, "api.user.login.bot_login_forbidden.app_error") + CheckUnauthorizedStatus(t, resp) + }) } func TestGetChannelMembersWithTeamData(t *testing.T) {
server/channels/app/bot.go+2 −0 modified@@ -614,5 +614,7 @@ func (a *App) ConvertUserToBot(rctx request.CTX, user *model.User) (*model.Bot, return nil, model.NewAppError("CreateBot", "app.bot.createbot.internal_error", nil, "", http.StatusInternalServerError).Wrap(err) } } + a.InvalidateCacheForUser(user.Id) + return bot, nil }
124547a9ef42[AI assisted] MM-62837: (#30268) (#30288)
2 files changed · +20 −0
server/channels/api4/user_test.go+19 −0 modified@@ -6194,6 +6194,25 @@ func TestConvertUserToBot(t *testing.T) { require.NoError(t, err) require.NotNil(t, bot) }) + + t.Run("user cannot login after being converted to bot", func(t *testing.T) { + // Create a new user + user := th.CreateUser() + + // Login as the new user to verify login works initially + _, _, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.NoError(t, err) + + // Convert user to bot + _, _, err = th.SystemAdminClient.ConvertUserToBot(context.Background(), user.Id) + require.NoError(t, err) + + // Try to login again - should fail + _, resp, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.Error(t, err) + CheckErrorID(t, err, "api.user.login.bot_login_forbidden.app_error") + CheckUnauthorizedStatus(t, resp) + }) } func TestGetChannelMembersWithTeamData(t *testing.T) {
server/channels/app/bot.go+1 −0 modified@@ -613,6 +613,7 @@ func (a *App) ConvertUserToBot(rctx request.CTX, user *model.User) (*model.Bot, if err := a.RevokeAllSessions(rctx, user.Id); err != nil { return nil, err } + a.InvalidateCacheForUser(user.Id) return bot, nil }
88523ceed8a7[AI assisted] MM-62837: (#30268) (#30287)
2 files changed · +20 −0
server/channels/api4/user_test.go+19 −0 modified@@ -6652,6 +6652,25 @@ func TestConvertUserToBot(t *testing.T) { require.NoError(t, err) require.NotNil(t, bot) }) + + t.Run("user cannot login after being converted to bot", func(t *testing.T) { + // Create a new user + user := th.CreateUser() + + // Login as the new user to verify login works initially + _, _, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.NoError(t, err) + + // Convert user to bot + _, _, err = th.SystemAdminClient.ConvertUserToBot(context.Background(), user.Id) + require.NoError(t, err) + + // Try to login again - should fail + _, resp, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.Error(t, err) + CheckErrorID(t, err, "api.user.login.bot_login_forbidden.app_error") + CheckUnauthorizedStatus(t, resp) + }) } func TestGetChannelMembersWithTeamData(t *testing.T) {
server/channels/app/bot.go+1 −0 modified@@ -617,6 +617,7 @@ func (a *App) ConvertUserToBot(rctx request.CTX, user *model.User) (*model.Bot, if err := a.RevokeAllSessions(rctx, user.Id); err != nil { return nil, err } + a.InvalidateCacheForUser(user.Id) return bot, nil }
bcd7a4c2bd85[AI assisted] MM-62837: (#30268) (#30286)
2 files changed · +20 −0
server/channels/api4/user_test.go+19 −0 modified@@ -6601,6 +6601,25 @@ func TestConvertUserToBot(t *testing.T) { require.NoError(t, err) require.NotNil(t, bot) }) + + t.Run("user cannot login after being converted to bot", func(t *testing.T) { + // Create a new user + user := th.CreateUser() + + // Login as the new user to verify login works initially + _, _, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.NoError(t, err) + + // Convert user to bot + _, _, err = th.SystemAdminClient.ConvertUserToBot(context.Background(), user.Id) + require.NoError(t, err) + + // Try to login again - should fail + _, resp, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.Error(t, err) + CheckErrorID(t, err, "api.user.login.bot_login_forbidden.app_error") + CheckUnauthorizedStatus(t, resp) + }) } func TestGetChannelMembersWithTeamData(t *testing.T) {
server/channels/app/bot.go+1 −0 modified@@ -617,6 +617,7 @@ func (a *App) ConvertUserToBot(rctx request.CTX, user *model.User) (*model.Bot, if err := a.RevokeAllSessions(rctx, user.Id); err != nil { return nil, err } + a.InvalidateCacheForUser(user.Id) return bot, nil }
fd356b62b4dd[AI assisted] MM-62837: (#30268)
2 files changed · +20 −0
server/channels/api4/user_test.go+19 −0 modified@@ -6601,6 +6601,25 @@ func TestConvertUserToBot(t *testing.T) { require.NoError(t, err) require.NotNil(t, bot) }) + + t.Run("user cannot login after being converted to bot", func(t *testing.T) { + // Create a new user + user := th.CreateUser() + + // Login as the new user to verify login works initially + _, _, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.NoError(t, err) + + // Convert user to bot + _, _, err = th.SystemAdminClient.ConvertUserToBot(context.Background(), user.Id) + require.NoError(t, err) + + // Try to login again - should fail + _, resp, err := th.Client.Login(context.Background(), user.Email, user.Password) + require.Error(t, err) + CheckErrorID(t, err, "api.user.login.bot_login_forbidden.app_error") + CheckUnauthorizedStatus(t, resp) + }) } func TestGetChannelMembersWithTeamData(t *testing.T) {
server/channels/app/bot.go+1 −0 modified@@ -617,6 +617,7 @@ func (a *App) ConvertUserToBot(rctx request.CTX, user *model.User) (*model.Bot, if err := a.RevokeAllSessions(rctx, user.Id); err != nil { return nil, err } + a.InvalidateCacheForUser(user.Id) return bot, nil }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-6rqh-8465-2xcwghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-2475ghsaADVISORY
- github.com/mattermost/mattermost/commit/124547a9ef424431e1e6cf09bdba6c1099d415deghsaWEB
- github.com/mattermost/mattermost/commit/40fd60714bd055e00c16301ba6dc0fddfc44e15eghsaWEB
- github.com/mattermost/mattermost/commit/88523ceed8a7547c4a4203a30e7c3a8097346280ghsaWEB
- github.com/mattermost/mattermost/commit/bcd7a4c2bd856dbb40fcda227b363fa5f6f548a7ghsaWEB
- github.com/mattermost/mattermost/commit/fd356b62b4dd3318d2c8019d2310abdd6ce24c8cghsaWEB
- mattermost.com/security-updatesghsaWEB
- pkg.go.dev/vuln/GO-2025-3610ghsaWEB
News mentions
0No linked articles in our index yet.