powerful but friendly backup program that runs in your tray, powered by restic devins.page/restray
go restic system-tray
2

Configure Feed

Select the types of activity you want to include in your feed.

fix: console security issue

the gui shell console wrote env stuff as `export`/`set` lines into the temp script opened by the terminal, letting shell history capture them. fixed now

this was not an issue for cli shell command, only gui shell operation. also appers to not be an issue on linux, just windows/mac

intergrav (Jul 1, 2026, 9:38 PM EDT) d3d1485b 3ed86866

+33 -24
+15 -6
cmd/restray/console_darwin.go
··· 11 11 ) 12 12 13 13 func consoleCmd(vars map[string]string, consoleMsg, tailMsg, tailFile, terminal string) *exec.Cmd { 14 + envFile, err := os.CreateTemp("", "restray-env-*") 15 + if err != nil { 16 + return nil 17 + } 18 + for k, v := range vars { 19 + fmt.Fprintf(envFile, "%s=%s\x00", k, v) 20 + } 21 + if p, _ := findRestic(); p != "" { 22 + fmt.Fprintf(envFile, "PATH=%s:%s\x00", filepath.Dir(p), os.Getenv("PATH")) 23 + } 24 + envFile.Close() 25 + 14 26 script, err := os.CreateTemp("", "restray-shell-*.sh") 15 27 if err != nil { 28 + os.Remove(envFile.Name()) 16 29 return nil 17 30 } 18 31 shell := os.Getenv("SHELL") ··· 20 33 shell = "/bin/zsh" 21 34 } 22 35 fmt.Fprintf(script, "#!/bin/sh\n") 23 - for k, v := range vars { 24 - fmt.Fprintf(script, "export %s=%q\n", k, v) 25 - } 26 - if p, _ := findRestic(); p != "" { 27 - fmt.Fprintf(script, "export PATH=%q:\"$PATH\"\n", filepath.Dir(p)) 28 - } 36 + fmt.Fprintf(script, "while IFS='=' read -r -d '' k v; do export \"$k=$v\"; done < %q\n", envFile.Name()) 37 + fmt.Fprintf(script, "rm -f %q\n", envFile.Name()) 29 38 fmt.Fprintf(script, "clear\n") 30 39 fmt.Fprintf(script, "rm -f %q\n", script.Name()) 31 40 fmt.Fprintf(script, "echo '%s'\n", consoleMsg)
+8 -10
cmd/restray/console_windows.go
··· 6 6 "fmt" 7 7 "os" 8 8 "os/exec" 9 - "path/filepath" 10 9 ) 11 10 12 11 func consoleCmd(vars map[string]string, consoleMsg, tailMsg, tailFile, _ string) *exec.Cmd { ··· 15 14 return nil 16 15 } 17 16 fmt.Fprintf(script, "@echo off\r\n") 18 - for k, v := range vars { 19 - fmt.Fprintf(script, "set %s=%s\r\n", k, v) 20 - } 21 - if p, _ := findRestic(); p != "" { 22 - fmt.Fprintf(script, "set PATH=%s;%%PATH%%\r\n", filepath.Dir(p)) 23 - } 17 + fmt.Fprintf(script, "cd /d \"%s\"\r\n", configDir()) 24 18 fmt.Fprintf(script, "echo %s\r\n", consoleMsg) 25 19 if tailFile != "" { 26 20 fmt.Fprintf(script, "echo %s\r\n", tailMsg) 27 21 fmt.Fprintf(script, "echo.\r\n") 28 22 fmt.Fprintf(script, "powershell -Command \"Get-Content -Path '%s' -Wait\"\r\n", tailFile) 29 23 } 30 - fmt.Fprintf(script, "cd /d %q\r\n", configDir()) 31 - fmt.Fprintf(script, "cmd /k\r\n") 32 24 script.Close() 33 - cmd := exec.Command("cmd", "/c", "start", "", script.Name()) 25 + 26 + cmd := exec.Command("cmd", "/c", "start", "", "cmd", "/k", script.Name()) 27 + env := os.Environ() 28 + for k, v := range vars { 29 + env = append(env, k+"="+v) 30 + } 31 + cmd.Env = envWithResticPath(env) 34 32 showConsole(cmd) 35 33 return cmd 36 34 }
+10 -8
cmd/restray/operations.go
··· 267 267 } 268 268 269 269 func envWithResticPath(env []string) []string { 270 - if p, _ := findRestic(); p != "" { 271 - dir := filepath.Dir(p) 272 - for i, e := range env { 273 - if strings.HasPrefix(e, "PATH=") { 274 - env[i] = "PATH=" + dir + string(os.PathListSeparator) + e[5:] 275 - break 276 - } 270 + p, _ := findRestic() 271 + if p == "" { 272 + return env 273 + } 274 + dir := filepath.Dir(p) 275 + for i, e := range env { 276 + if k, v, ok := strings.Cut(e, "="); ok && strings.EqualFold(k, "PATH") { 277 + env[i] = k + "=" + dir + string(os.PathListSeparator) + v 278 + return env 277 279 } 278 280 } 279 - return env 281 + return append(env, "PATH="+dir) 280 282 } 281 283 282 284 func hookCmd(hook string, prof Profile, extraEnv ...string) *exec.Cmd {