VYPR
High severityNVD Advisory· Published Jun 30, 2025· Updated Jun 30, 2025

File Browser vulnerable to command execution allowlist bypass

CVE-2025-52995

Description

File Browser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit files. Prior to version 2.33.10, the implementation of the allowlist is erroneous, allowing a user to execute more shell commands than they are authorized for. The concrete impact of this vulnerability depends on the commands configured, and the binaries installed on the server or in the container image. Due to the missing separation of scopes on the OS-level, this could give an attacker access to all files managed the application, including the File Browser database. This issue has been patched in version 2.33.10.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/filebrowser/filebrowser/v2Go
< 2.33.102.33.10
github.com/filebrowser/filebrowserGo
<= 1.11.0

Affected products

1

Patches

1
4d830f707fc4

fix: correctly check if command is allowed when using shell

https://github.com/filebrowser/filebrowserHenrique DiasJun 26, 2025via ghsa
4 files changed · +21 30
  • http/commands.go+12 2 modified
    @@ -6,6 +6,7 @@ import (
     	"log"
     	"net/http"
     	"os/exec"
    +	"slices"
     	"strings"
     	"time"
     
    @@ -60,15 +61,24 @@ 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)
     		}
     		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)
     		}
    
  • runner/parser.go+8 17 modified
    @@ -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
    +func ParseCommand(s *settings.Settings, raw string) (command []string, name string, err error) {
    +	name, args, err := SplitCommandAndArgs(raw)
    +	if err != nil {
    +		return
    +	}
     
     	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, name)
     		command = append(command, args...)
     	} else {
    -		command = append(s.Shell, raw) //nolint:gocritic
    +		command = append(s.Shell, raw)
     	}
     
    -	return command, nil
    +	return command, name, nil
     }
    
  • runner/runner.go+1 1 modified
    @@ -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
     	}
    
  • users/users.go+0 10 modified
    @@ -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)
    -}
    

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

7

News mentions

0

No linked articles in our index yet.