коммит произвёл
GitHub
родитель
c64ff9d84e
Коммит
c654f0502f
@@ -6,6 +6,7 @@ package api4
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -17,6 +18,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mattermost/mattermost/server/public/model"
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
||||||
|
"github.com/mattermost/mattermost/server/v8/channels/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateCommand(t *testing.T) {
|
func TestCreateCommand(t *testing.T) {
|
||||||
@@ -956,14 +958,17 @@ func TestExecuteInvalidCommand(t *testing.T) {
|
|||||||
|
|
||||||
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
defer func() {
|
defer func() {
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
}()
|
}()
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065" })
|
||||||
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
rc := &model.CommandResponse{}
|
rc := &model.CommandResponse{}
|
||||||
@@ -1029,14 +1034,17 @@ func TestExecuteGetCommand(t *testing.T) {
|
|||||||
|
|
||||||
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
defer func() {
|
defer func() {
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
}()
|
}()
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065" })
|
||||||
|
|
||||||
token := model.NewId()
|
token := model.NewId()
|
||||||
expectedCommandResponse := &model.CommandResponse{
|
expectedCommandResponse := &model.CommandResponse{
|
||||||
@@ -1092,14 +1100,17 @@ func TestExecutePostCommand(t *testing.T) {
|
|||||||
|
|
||||||
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
defer func() {
|
defer func() {
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
}()
|
}()
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065" })
|
||||||
|
|
||||||
token := model.NewId()
|
token := model.NewId()
|
||||||
expectedCommandResponse := &model.CommandResponse{
|
expectedCommandResponse := &model.CommandResponse{
|
||||||
@@ -1264,16 +1275,19 @@ func TestExecuteCommandInDirectMessageChannel(t *testing.T) {
|
|||||||
|
|
||||||
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
defer func() {
|
defer func() {
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
}()
|
}()
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065" })
|
||||||
|
|
||||||
// create a team that the user isn't a part of
|
// create a team that the user isn't a part of
|
||||||
team2 := th.CreateTeam()
|
team2 := th.CreateTeam()
|
||||||
@@ -1329,16 +1343,19 @@ func TestExecuteCommandInTeamUserIsNotOn(t *testing.T) {
|
|||||||
|
|
||||||
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
defer func() {
|
defer func() {
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
}()
|
}()
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065" })
|
||||||
|
|
||||||
// create a team that the user isn't a part of
|
// create a team that the user isn't a part of
|
||||||
team2 := th.CreateTeam()
|
team2 := th.CreateTeam()
|
||||||
@@ -1407,16 +1424,19 @@ func TestExecuteCommandReadOnly(t *testing.T) {
|
|||||||
|
|
||||||
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
defer func() {
|
defer func() {
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
}()
|
}()
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
||||||
})
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065" })
|
||||||
|
|
||||||
expectedCommandResponse := &model.CommandResponse{
|
expectedCommandResponse := &model.CommandResponse{
|
||||||
Text: "test post command response",
|
Text: "test post command response",
|
||||||
@@ -1494,3 +1514,124 @@ func TestExecuteCommandReadOnly(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
CheckBadRequestStatus(t, resp)
|
CheckBadRequestStatus(t, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExecuteCommandResponseURLUsesSiteURL(t *testing.T) {
|
||||||
|
mainHelper.Parallel(t)
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
client := th.Client
|
||||||
|
channel := th.BasicChannel
|
||||||
|
|
||||||
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
|
defer func() {
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
|
}()
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
||||||
|
|
||||||
|
// Set a SiteURL that differs from the test client's Host header (localhost).
|
||||||
|
// This verifies that response_url uses the configured SiteURL, not the Host header.
|
||||||
|
// Before the fix (MM-67142), response_url would contain "localhost" and fail this check.
|
||||||
|
expectedSiteURL := "http://mattermost.example.com"
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = expectedSiteURL })
|
||||||
|
|
||||||
|
var receivedResponseURL string
|
||||||
|
expectedCommandResponse := &model.CommandResponse{
|
||||||
|
Text: "test response_url command response",
|
||||||
|
ResponseType: model.CommandResponseTypeInChannel,
|
||||||
|
}
|
||||||
|
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
err := r.ParseForm()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Capture the response_url sent by the server
|
||||||
|
receivedResponseURL = r.FormValue("response_url")
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
||||||
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
postCmd := &model.Command{
|
||||||
|
CreatorId: th.BasicUser.Id,
|
||||||
|
TeamId: th.BasicTeam.Id,
|
||||||
|
URL: ts.URL,
|
||||||
|
Method: model.CommandMethodPost,
|
||||||
|
Trigger: "testrespurl",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, appErr := th.App.CreateCommand(postCmd)
|
||||||
|
require.Nil(t, appErr, "failed to create command")
|
||||||
|
|
||||||
|
_, _, err := client.ExecuteCommand(context.Background(), channel.Id, "/testrespurl")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Verify response_url starts with the configured SiteURL, not the Host header
|
||||||
|
require.True(t, strings.HasPrefix(receivedResponseURL, expectedSiteURL),
|
||||||
|
"response_url should start with configured SiteURL %q, but got %q", expectedSiteURL, receivedResponseURL)
|
||||||
|
|
||||||
|
// Verify warning is logged when Host header differs from SiteURL
|
||||||
|
require.NoError(t, th.TestLogger.Flush())
|
||||||
|
testlib.AssertLog(t, th.LogBuffer, mlog.LvlWarn.Name, "Request hostname differs from configured SiteURL. The configured SiteURL will be used for the slash command response URL.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExecuteCustomCommandRequiresSiteURL(t *testing.T) {
|
||||||
|
mainHelper.Parallel(t)
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
client := th.Client
|
||||||
|
channel := th.BasicChannel
|
||||||
|
|
||||||
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||||
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||||
|
siteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||||
|
defer func() {
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
||||||
|
})
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SiteURL = &siteURL })
|
||||||
|
}()
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
||||||
|
|
||||||
|
// Set SiteURL to a valid value first so we can create the command
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065" })
|
||||||
|
|
||||||
|
// Create a custom command
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
fmt.Fprintln(w, `{"text": "response"}`)
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
postCmd := &model.Command{
|
||||||
|
CreatorId: th.BasicUser.Id,
|
||||||
|
TeamId: th.BasicTeam.Id,
|
||||||
|
URL: ts.URL,
|
||||||
|
Method: model.CommandMethodPost,
|
||||||
|
Trigger: "customcmd",
|
||||||
|
}
|
||||||
|
_, appErr := th.App.CreateCommand(postCmd)
|
||||||
|
require.Nil(t, appErr, "failed to create command")
|
||||||
|
|
||||||
|
// Now set SiteURL to empty
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "" })
|
||||||
|
|
||||||
|
// Try to execute the custom command - should fail because SiteURL is required for custom commands
|
||||||
|
_, resp, err := client.ExecuteCommand(context.Background(), channel.Id, "/customcmd")
|
||||||
|
require.Error(t, err)
|
||||||
|
CheckBadRequestStatus(t, resp)
|
||||||
|
CheckErrorID(t, err, "api.command.execute_command.site_url_required.app_error")
|
||||||
|
|
||||||
|
// Built-in commands should still work without SiteURL
|
||||||
|
_, _, err = client.ExecuteCommand(context.Background(), channel.Id, "/echo test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|||||||
@@ -475,11 +475,23 @@ func (a *App) tryExecuteCustomCommand(c request.CTX, args *model.CommandArgs, tr
|
|||||||
p[key] = values
|
p[key] = values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use configured SiteURL for response_url to prevent SSRF via Host header spoofing (MM-67142)
|
||||||
|
siteURL := *a.Config().ServiceSettings.SiteURL
|
||||||
|
if siteURL == "" {
|
||||||
|
return cmd, nil, model.NewAppError("tryExecuteCustomCommand", "api.command.execute_command.site_url_required.app_error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
if siteURL != args.SiteURL {
|
||||||
|
c.Logger().Warn(i18n.T("api.command.execute_command.provided_site_url_different.app_error"),
|
||||||
|
mlog.String("request_host", args.SiteURL),
|
||||||
|
mlog.String("configured_site_url", siteURL),
|
||||||
|
mlog.String("command", trigger))
|
||||||
|
}
|
||||||
|
|
||||||
hook, appErr := a.CreateCommandWebhook(cmd.Id, args)
|
hook, appErr := a.CreateCommandWebhook(cmd.Id, args)
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
return cmd, nil, model.NewAppError("command", "api.command.execute_command.failed.app_error", map[string]any{"Trigger": trigger}, "", http.StatusInternalServerError).Wrap(appErr)
|
return cmd, nil, model.NewAppError("command", "api.command.execute_command.failed.app_error", map[string]any{"Trigger": trigger}, "", http.StatusInternalServerError).Wrap(appErr)
|
||||||
}
|
}
|
||||||
p.Set("response_url", args.SiteURL+"/hooks/commands/"+hook.Id)
|
p.Set("response_url", siteURL+"/hooks/commands/"+hook.Id)
|
||||||
|
|
||||||
return a.DoCommandRequest(c, cmd, p)
|
return a.DoCommandRequest(c, cmd, p)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,7 +269,12 @@ func (a *App) getDynamicListArgument(c request.CTX, commandArgs *model.CommandAr
|
|||||||
params.Add("team_id", commandArgs.TeamId)
|
params.Add("team_id", commandArgs.TeamId)
|
||||||
params.Add("root_id", commandArgs.RootId)
|
params.Add("root_id", commandArgs.RootId)
|
||||||
params.Add("user_id", commandArgs.UserId)
|
params.Add("user_id", commandArgs.UserId)
|
||||||
params.Add("site_url", commandArgs.SiteURL)
|
|
||||||
|
// Use configured SiteURL to prevent SSRF via Host header spoofing (MM-67142)
|
||||||
|
siteURL := *a.Config().ServiceSettings.SiteURL
|
||||||
|
if siteURL != "" {
|
||||||
|
params.Add("site_url", siteURL)
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := a.doPluginRequest(c, "GET", dynamicArg.FetchURL, params, nil)
|
resp, err := a.doPluginRequest(c, "GET", dynamicArg.FetchURL, params, nil)
|
||||||
|
|
||||||
|
|||||||
@@ -679,6 +679,14 @@
|
|||||||
"id": "api.command.execute_command.not_found.app_error",
|
"id": "api.command.execute_command.not_found.app_error",
|
||||||
"translation": "Command with a trigger of '{{.Trigger}}' not found. To send a message beginning with \"/\", try adding an empty space at the beginning of the message."
|
"translation": "Command with a trigger of '{{.Trigger}}' not found. To send a message beginning with \"/\", try adding an empty space at the beginning of the message."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "api.command.execute_command.provided_site_url_different.app_error",
|
||||||
|
"translation": "Request hostname differs from configured SiteURL. The configured SiteURL will be used for the slash command response URL."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "api.command.execute_command.site_url_required.app_error",
|
||||||
|
"translation": "SiteURL must be configured to use slash commands"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "api.command.execute_command.start.app_error",
|
"id": "api.command.execute_command.start.app_error",
|
||||||
"translation": "No command trigger found."
|
"translation": "No command trigger found."
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user