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

File Browser Allows Execution of Shell Commands That Can Spawn Other Commands

CVE-2025-52903

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. In version 2.32.0, the Command Execution feature of File Browser only allows the execution of shell command which have been predefined on a user-specific allowlist. Many tools allow the execution of arbitrary different commands, rendering this limitation void. The concrete impact depends on the commands being granted to the attacker, but the large number of standard commands allowing the execution of subcommands makes it likely that every user having the Execute commands permissions can exploit this vulnerability. Everyone who can exploit it will have full code execution rights with the uid of the server process. Until this issue is fixed, the maintainers recommend to completely disable Execute commands for all accounts. Since the command execution is an inherently dangerous feature that is not used by all deployments, it should be possible to completely disable it in the application's configuration. As a defense-in-depth measure, organizations not requiring command execution should operate the Filebrowser from a distroless container image. A patch version has been pushed to disable the feature for all existent installations, and making it opt-in. A warning has been added to the documentation and is printed on the console if the feature is enabled. Due to the project being in maintenance-only mode, the bug has not been fixed. The fix is tracked on pull request 5199.

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

8

News mentions

0

No linked articles in our index yet.