fix: correctly check if command is allowed when using shell

This commit is contained in:
Henrique Dias 2025-06-26 21:09:16 +02:00
parent f84a6db680
commit 4d830f707f
No known key found for this signature in database
4 changed files with 25 additions and 34 deletions

View File

@ -6,6 +6,7 @@ import (
"log"
"net/http"
"os/exec"
"slices"
"strings"
"time"
@ -60,7 +61,16 @@ var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *d
}
}
command, err := runner.ParseCommand(d.settings, raw)
// Fail fast
if !d.server.EnableExec || !d.user.Perm.Execute {
if err := conn.WriteMessage(websocket.TextMessage, cmdNotAllowed); err != nil { //nolint:govet
wsErr(conn, r, http.StatusInternalServerError, err)
}
return 0, nil
}
command, name, err := runner.ParseCommand(d.settings, raw)
if err != nil {
if err := conn.WriteMessage(websocket.TextMessage, []byte(err.Error())); err != nil { //nolint:govet
wsErr(conn, r, http.StatusInternalServerError, err)
@ -68,7 +78,7 @@ var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *d
return 0, nil
}
if !d.server.EnableExec || !d.user.CanExecute(command[0]) {
if !slices.Contains(d.user.Commands, name) {
if err := conn.WriteMessage(websocket.TextMessage, cmdNotAllowed); err != nil { //nolint:govet
wsErr(conn, r, http.StatusInternalServerError, err)
}

View File

@ -1,33 +1,24 @@
package runner
import (
"os/exec"
"github.com/filebrowser/filebrowser/v2/settings"
)
// ParseCommand parses the command taking in account if the current
// instance uses a shell to run the commands or just calls the binary
// directly.
func ParseCommand(s *settings.Settings, raw string) ([]string, error) {
var command []string
if len(s.Shell) == 0 || s.Shell[0] == "" {
cmd, args, err := SplitCommandAndArgs(raw)
if err != nil {
return nil, err
}
_, err = exec.LookPath(cmd)
if err != nil {
return nil, err
}
command = append(command, cmd)
command = append(command, args...)
} else {
command = append(s.Shell, raw) //nolint:gocritic
func ParseCommand(s *settings.Settings, raw string) (command []string, name string, err error) {
name, args, err := SplitCommandAndArgs(raw)
if err != nil {
return
}
return command, nil
if len(s.Shell) == 0 || s.Shell[0] == "" {
command = append(command, name)
command = append(command, args...)
} else {
command = append(s.Shell, raw)
}
return command, name, nil
}

View File

@ -60,7 +60,7 @@ func (r *Runner) exec(raw, evt, path, dst string, user *users.User) error {
raw = strings.TrimSpace(strings.TrimSuffix(raw, "&"))
}
command, err := ParseCommand(r.Settings, raw)
command, _, err := ParseCommand(r.Settings, raw)
if err != nil {
return err
}

View File

@ -2,7 +2,6 @@ package users
import (
"path/filepath"
"slices"
"github.com/spf13/afero"
@ -104,12 +103,3 @@ func (u *User) Clean(baseScope string, fields ...string) error {
func (u *User) FullPath(path string) string {
return afero.FullBaseFsPath(u.Fs.(*afero.BasePathFs), path)
}
// CanExecute checks if an user can execute a specific command.
func (u *User) CanExecute(command string) bool {
if !u.Perm.Execute {
return false
}
return slices.Contains(u.Commands, command)
}