Admin RCE via prepackaged plugins by way of misconfigured imports directory
Description
Mattermost versions 10.8.x <= 10.8.3, 10.5.x <= 10.5.8, 9.11.x <= 9.11.17, 10.10.x <= 10.10.1, 10.9.x <= 10.9.3 fail to validate import directory path configuration which allows admin users to execute arbitrary code via malicious plugin upload to prepackaged plugins directory
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/mattermost/mattermost-serverGo | >= 10.8.0, < 10.8.4 | 10.8.4 |
github.com/mattermost/mattermost-serverGo | >= 10.5.0, < 10.5.9 | 10.5.9 |
github.com/mattermost/mattermost-serverGo | >= 9.11.0, < 9.11.18 | 9.11.18 |
github.com/mattermost/mattermost-serverGo | >= 10.10.0, < 10.10.2 | 10.10.2 |
github.com/mattermost/mattermost-serverGo | >= 10.9.0, < 10.9.4 | 10.9.4 |
github.com/mattermost/mattermost/server/v8Go | < 8.0.0-20250707221302-a8fa77f107ef | 8.0.0-20250707221302-a8fa77f107ef |
Affected products
1- Range: 10.8.0
Patches
64ff68eea0a3fMM-64779: Upload type validation. (#33351) (#33358)
2 files changed · +10 −0
server/i18n/en.json+4 −0 modified@@ -3850,6 +3850,10 @@ "id": "api.upload.get_upload.forbidden.app_error", "translation": "Failed to get upload." }, + { + "id": "api.upload.invalid_type_for_shared_channel.app_error", + "translation": "Failed to upload file. Upload channel is not shared with remote." + }, { "id": "api.upload.upload_data.invalid_content_length", "translation": "Invalid Content-Length."
server/platform/services/sharedchannel/attachment.go+6 −0 modified@@ -191,6 +191,12 @@ func (scs *Service) onReceiveUploadCreate(msg model.RemoteClusterMsg, rc *model. map[string]any{"channelId": us.ChannelId}, "", http.StatusRequestEntityTooLarge) } + // validate upload type for shared channels - only allow attachments + if us.Type != model.UploadTypeAttachment { + return model.NewAppError("onReceiveUploadCreate", "api.upload.invalid_type_for_shared_channel.app_error", + nil, "", http.StatusBadRequest) + } + us.RemoteId = rc.RemoteId // don't let remotes try to impersonate each other // create upload session.
047a2c640717MM-64779: Upload type validation. (#33351) (#33356)
2 files changed · +10 −0
server/i18n/en.json+4 −0 modified@@ -3858,6 +3858,10 @@ "id": "api.upload.get_upload.forbidden.app_error", "translation": "Failed to get upload." }, + { + "id": "api.upload.invalid_type_for_shared_channel.app_error", + "translation": "Failed to upload file. Upload channel is not shared with remote." + }, { "id": "api.upload.upload_data.invalid_content_length", "translation": "Invalid Content-Length."
server/platform/services/sharedchannel/attachment.go+6 −0 modified@@ -191,6 +191,12 @@ func (scs *Service) onReceiveUploadCreate(msg model.RemoteClusterMsg, rc *model. map[string]any{"channelId": us.ChannelId}, "", http.StatusRequestEntityTooLarge) } + // validate upload type for shared channels - only allow attachments + if us.Type != model.UploadTypeAttachment { + return model.NewAppError("onReceiveUploadCreate", "api.upload.invalid_type_for_shared_channel.app_error", + nil, "", http.StatusBadRequest) + } + us.RemoteId = rc.RemoteId // don't let remotes try to impersonate each other // create upload session.
b38e2eccda18MM-64779: Upload type validation. (#33351) (#33355)
2 files changed · +10 −0
server/i18n/en.json+4 −0 modified@@ -3894,6 +3894,10 @@ "id": "api.upload.get_upload.forbidden.app_error", "translation": "Failed to get upload." }, + { + "id": "api.upload.invalid_type_for_shared_channel.app_error", + "translation": "Failed to upload file. Upload channel is not shared with remote." + }, { "id": "api.upload.upload_data.invalid_content_length", "translation": "Invalid Content-Length."
server/platform/services/sharedchannel/attachment.go+6 −0 modified@@ -191,6 +191,12 @@ func (scs *Service) onReceiveUploadCreate(msg model.RemoteClusterMsg, rc *model. map[string]any{"channelId": us.ChannelId}, "", http.StatusRequestEntityTooLarge) } + // validate upload type for shared channels - only allow attachments + if us.Type != model.UploadTypeAttachment { + return model.NewAppError("onReceiveUploadCreate", "api.upload.invalid_type_for_shared_channel.app_error", + nil, "", http.StatusBadRequest) + } + us.RemoteId = rc.RemoteId // don't let remotes try to impersonate each other // create upload session.
96665b9b98a1MM-64779: Upload type validation. (#33351) (#33354)
2 files changed · +10 −0
server/i18n/en.json+4 −0 modified@@ -3910,6 +3910,10 @@ "id": "api.upload.get_upload.forbidden.app_error", "translation": "Failed to get upload." }, + { + "id": "api.upload.invalid_type_for_shared_channel.app_error", + "translation": "Failed to upload file. Upload channel is not shared with remote." + }, { "id": "api.upload.upload_data.invalid_content_length", "translation": "Invalid Content-Length."
server/platform/services/sharedchannel/attachment.go+6 −0 modified@@ -191,6 +191,12 @@ func (scs *Service) onReceiveUploadCreate(msg model.RemoteClusterMsg, rc *model. map[string]any{"channelId": us.ChannelId}, "", http.StatusRequestEntityTooLarge) } + // validate upload type for shared channels - only allow attachments + if us.Type != model.UploadTypeAttachment { + return model.NewAppError("onReceiveUploadCreate", "api.upload.invalid_type_for_shared_channel.app_error", + nil, "", http.StatusBadRequest) + } + us.RemoteId = rc.RemoteId // don't let remotes try to impersonate each other // create upload session.
439464883aa1MM-64779: Upload type validation. (#33351) (#33359)
2 files changed · +10 −0
server/i18n/en.json+4 −0 modified@@ -3770,6 +3770,10 @@ "id": "api.upload.get_upload.forbidden.app_error", "translation": "Failed to get upload." }, + { + "id": "api.upload.invalid_type_for_shared_channel.app_error", + "translation": "Failed to upload file. Upload channel is not shared with remote." + }, { "id": "api.upload.upload_data.invalid_content_length", "translation": "Invalid Content-Length."
server/platform/services/sharedchannel/attachment.go+6 −0 modified@@ -187,6 +187,12 @@ func (scs *Service) onReceiveUploadCreate(msg model.RemoteClusterMsg, rc *model. map[string]any{"channelId": us.ChannelId}, "", http.StatusRequestEntityTooLarge) } + // validate upload type for shared channels - only allow attachments + if us.Type != model.UploadTypeAttachment { + return model.NewAppError("onReceiveUploadCreate", "api.upload.invalid_type_for_shared_channel.app_error", + nil, "", http.StatusBadRequest) + } + us.RemoteId = rc.RemoteId // don't let remotes try to impersonate each other // create upload session.
a8fa77f107efMM-64779: Upload type validation. (#33351)
2 files changed · +10 −0
server/i18n/en.json+4 −0 modified@@ -3914,6 +3914,10 @@ "id": "api.upload.get_upload.forbidden.app_error", "translation": "Failed to get upload." }, + { + "id": "api.upload.invalid_type_for_shared_channel.app_error", + "translation": "Failed to upload file. Upload channel is not shared with remote." + }, { "id": "api.upload.upload_data.invalid_content_length", "translation": "Invalid Content-Length."
server/platform/services/sharedchannel/attachment.go+6 −0 modified@@ -191,6 +191,12 @@ func (scs *Service) onReceiveUploadCreate(msg model.RemoteClusterMsg, rc *model. map[string]any{"channelId": us.ChannelId}, "", http.StatusRequestEntityTooLarge) } + // validate upload type for shared channels - only allow attachments + if us.Type != model.UploadTypeAttachment { + return model.NewAppError("onReceiveUploadCreate", "api.upload.invalid_type_for_shared_channel.app_error", + nil, "", http.StatusBadRequest) + } + us.RemoteId = rc.RemoteId // don't let remotes try to impersonate each other // create upload session.
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
10- github.com/advisories/GHSA-qx3f-6vq3-8j8mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-9079ghsaADVISORY
- github.com/mattermost/mattermost/commit/047a2c64071749367fe02d2162f6103a3d31a883ghsaWEB
- github.com/mattermost/mattermost/commit/439464883aa16a329c23cd6274c4cca7e88e238fghsaWEB
- github.com/mattermost/mattermost/commit/4ff68eea0a3f3777032d31a1a82f4b1fb492a1acghsaWEB
- github.com/mattermost/mattermost/commit/96665b9b98a17534fcd515982a2eb26950581e41ghsaWEB
- github.com/mattermost/mattermost/commit/a8fa77f107efe83f09a779f8e67cbecf236b0032ghsaWEB
- github.com/mattermost/mattermost/commit/b38e2eccda182212a8032539658723c7d87e0b7eghsaWEB
- mattermost.com/security-updatesghsaWEB
- pkg.go.dev/vuln/GO-2025-3977ghsaWEB
News mentions
0No linked articles in our index yet.