From 64f833d8f790e730fd144b306c230a4916405876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 16 Jul 2026 21:34:33 +0800 Subject: [PATCH] boxx: Fix unsafe installation --- experimental/boxdd/cmd_run_windows.go | 16 +++++++++++++++- experimental/boxdd/cmd_service_windows.go | 10 ++++++++-- experimental/boxdd/security_windows.go | 17 +++++++---------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/experimental/boxdd/cmd_run_windows.go b/experimental/boxdd/cmd_run_windows.go index d57f93f36..7ed25fbc2 100644 --- a/experimental/boxdd/cmd_run_windows.go +++ b/experimental/boxdd/cmd_run_windows.go @@ -12,6 +12,17 @@ import ( "golang.org/x/sys/windows/svc/eventlog" ) +var commandRunFlagAllowUnsafeInstallation bool + +func init() { + commandRun.Flags().BoolVar( + &commandRunFlagAllowUnsafeInstallation, + "allow-unsafe-installation-directory-permissions", + false, + "allow unsafe daemon working directory ancestor permissions", + ) +} + func runService() (bool, error) { isWindowsService, err := svc.IsWindowsService() if err != nil { @@ -27,7 +38,10 @@ func preparePlatformWorkingDirectory() error { if listenAddress != "" { return os.MkdirAll(workingDirectory, 0o700) } - serviceWorkingDirectory, err := resolveWindowsServiceWorkingDirectory(workingDirectory) + serviceWorkingDirectory, err := resolveWindowsServiceWorkingDirectory( + workingDirectory, + commandRunFlagAllowUnsafeInstallation, + ) if err != nil { return err } diff --git a/experimental/boxdd/cmd_service_windows.go b/experimental/boxdd/cmd_service_windows.go index 6db36c01c..c890321fc 100644 --- a/experimental/boxdd/cmd_service_windows.go +++ b/experimental/boxdd/cmd_service_windows.go @@ -66,7 +66,7 @@ func addPlatformServiceCommands() { &commandServiceFlagAllowUnsafeInstallation, "allow-unsafe-installation-directory-permissions", false, - "skip installation path security validation and permission hardening", + "allow unsafe installation path security and daemon working directory ancestor permissions", ) commandService.AddCommand(commandServiceInstall) commandService.AddCommand(commandServiceUninstall) @@ -128,7 +128,10 @@ func serviceInstall() error { if err != nil { return E.Cause(err, "get executable path") } - serviceWorkingDirectory, err := resolveWindowsServiceWorkingDirectory(commandServiceFlagWorkingDirectory) + serviceWorkingDirectory, err := resolveWindowsServiceWorkingDirectory( + commandServiceFlagWorkingDirectory, + commandServiceFlagAllowUnsafeInstallation, + ) if err != nil { return E.Cause(err, "validate working directory") } @@ -146,6 +149,9 @@ func serviceInstall() error { } defer manager.Disconnect() arguments := []string{"run", "--working-directory", serviceWorkingDirectory} + if commandServiceFlagAllowUnsafeInstallation { + arguments = append(arguments, "--allow-unsafe-installation-directory-permissions") + } config := mgr.Config{ DisplayName: serviceDisplayName, Description: serviceDescriptionText, diff --git a/experimental/boxdd/security_windows.go b/experimental/boxdd/security_windows.go index 6be631942..f17b11e17 100644 --- a/experimental/boxdd/security_windows.go +++ b/experimental/boxdd/security_windows.go @@ -67,7 +67,7 @@ func secureWindowsInstallation(executablePath string, allowUnsafeInstallation bo if err != nil { return "", err } - err = validateInstallationAncestors(filepath.Dir(installationDirectory), volumeRoot, true) + err = validateInstallationAncestors(filepath.Dir(installationDirectory), volumeRoot, false) if err != nil { return "", err } @@ -336,7 +336,7 @@ func validateFixedNTFSVolume(path string) (string, error) { return filepath.Clean(volumePath), nil } -func resolveWindowsServiceWorkingDirectory(path string) (string, error) { +func resolveWindowsServiceWorkingDirectory(path string, allowUnsafePermissions bool) (string, error) { if path == "" { return "", E.New("missing daemon working directory") } @@ -363,18 +363,18 @@ func resolveWindowsServiceWorkingDirectory(path string) (string, error) { if strings.EqualFold(cleanPath, filepath.Clean(volumeRoot)) { return "", E.New("daemon working directory must not be a volume root") } - err = validateInstallationAncestors(parentPath, volumeRoot, true) + err = validateInstallationAncestors(parentPath, volumeRoot, allowUnsafePermissions) if err != nil { return "", E.Cause(err, "validate daemon working directory ancestors") } return cleanPath, nil } -func validateInstallationAncestors(path string, volumeRoot string, validatePermissions bool) error { +func validateInstallationAncestors(path string, volumeRoot string, allowUnsafePermissions bool) error { currentPath := filepath.Clean(path) cleanVolumeRoot := filepath.Clean(volumeRoot) for { - err := validateInstallationAncestor(currentPath, validatePermissions) + err := validateInstallationAncestor(currentPath, allowUnsafePermissions) if err != nil { return err } @@ -389,7 +389,7 @@ func validateInstallationAncestors(path string, volumeRoot string, validatePermi } } -func validateInstallationAncestor(path string, validatePermissions bool) error { +func validateInstallationAncestor(path string, allowUnsafePermissions bool) error { attributes, err := windowsFileAttributes(path) if err != nil { return err @@ -400,9 +400,6 @@ func validateInstallationAncestor(path string, validatePermissions bool) error { if attributes&windows.FILE_ATTRIBUTE_REPARSE_POINT != 0 { return E.New("installation ancestor is a reparse point: ", path) } - if !validatePermissions { - return nil - } descriptor, err := windows.GetNamedSecurityInfo( path, windows.SE_FILE_OBJECT, @@ -443,7 +440,7 @@ func validateInstallationAncestor(path string, validatePermissions bool) error { continue } principal := (*windows.SID)(unsafe.Pointer(&accessControlEntry.SidStart)) - if !trustedAdministrativeUser(principal) { + if !trustedAdministrativeUser(principal) && !allowUnsafePermissions { return E.New("installation ancestor is replaceable by an unprivileged principal: ", path) } }