diff --git a/api/exec/compose_stack.go b/api/exec/compose_stack.go index bd9985cd4..1937a4522 100644 --- a/api/exec/compose_stack.go +++ b/api/exec/compose_stack.go @@ -53,7 +53,7 @@ func (manager *ComposeStackManager) Up(ctx context.Context, stack *portainer.Sta return errors.Wrap(err, "failed to create env file") } - filePaths := stackutils.GetStackFilePaths(stack, false) + filePaths := stackutils.GetStackFilePaths(stack, true) err = manager.deployer.Deploy(ctx, filePaths, libstack.DeployOptions{ Options: libstack.Options{ WorkingDir: stack.ProjectPath, @@ -106,7 +106,7 @@ func (manager *ComposeStackManager) Pull(ctx context.Context, stack *portainer.S return errors.Wrap(err, "failed to create env file") } - filePaths := stackutils.GetStackFilePaths(stack, false) + filePaths := stackutils.GetStackFilePaths(stack, true) err = manager.deployer.Pull(ctx, filePaths, libstack.Options{ WorkingDir: stack.ProjectPath, EnvFilePath: envFilePath, diff --git a/api/exec/swarm_stack.go b/api/exec/swarm_stack.go index b16cfe11a..3dcdbec2c 100644 --- a/api/exec/swarm_stack.go +++ b/api/exec/swarm_stack.go @@ -94,7 +94,7 @@ func (manager *SwarmStackManager) Logout(endpoint *portainer.Endpoint) error { // Deploy executes the docker stack deploy command. func (manager *SwarmStackManager) Deploy(stack *portainer.Stack, prune bool, pullImage bool, endpoint *portainer.Endpoint) error { - filePaths := stackutils.GetStackFilePaths(stack, false) + filePaths := stackutils.GetStackFilePaths(stack, true) command, args, err := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint) if err != nil { return err diff --git a/api/stacks/stackutils/util.go b/api/stacks/stackutils/util.go index b1c8f17ba..a7214546f 100644 --- a/api/stacks/stackutils/util.go +++ b/api/stacks/stackutils/util.go @@ -15,6 +15,10 @@ func UserIsAdminOrEndpointAdmin(user *portainer.User, endpointID portainer.Endpo } // GetStackFilePaths returns a list of file paths based on stack project path +// If absolute is false, the path sanitization step will be skipped, which makes the returning +// paths vulnerable to path traversal attacks. Thus, the followed function using the returning +// paths are responsible to sanitize the raw paths +// If absolute is true, the raw paths will be sanitized func GetStackFilePaths(stack *portainer.Stack, absolute bool) []string { if !absolute { return append([]string{stack.EntryPoint}, stack.AdditionalFiles...)