@@ -2,12 +2,15 @@ package module
22
33import (
44 "context"
5+ "errors"
56 "fmt"
6- "io/ioutil "
7+ "log/slog "
78 "os"
89 "os/exec"
10+ "path/filepath"
911
1012 "github.com/hashicorp/go-multierror"
13+
1114 "github.com/selesy/lichen/internal/buildinfo"
1215 "github.com/selesy/lichen/internal/model"
1316)
@@ -50,20 +53,43 @@ func goVersion(ctx context.Context, paths []string) (string, error) {
5053 return "" , err
5154 }
5255
53- tempDir , err := ioutil .TempDir ("" , "lichen" )
56+ // normalize the path
57+ goBin , err = filepath .Abs (goBin )
58+ if err != nil {
59+ return "" , err
60+ }
61+ // resolve symlinks to prevent directory traversal attacks
62+ goBin , err = filepath .EvalSymlinks (goBin )
63+ if err != nil {
64+ return "" , err
65+ }
66+
67+ // Validation: Ensure we actually found a 'go' binary
68+ if filepath .Base (goBin ) != "go" && filepath .Base (goBin ) != "go.exe" {
69+ return "" , errors .New ("unexpected binary resolved" )
70+ }
71+
72+ tempDir , err := os .MkdirTemp ("" , "lichen" )
5473 if err != nil {
5574 return "" , fmt .Errorf ("failed to create temp directory: %w" , err )
5675 }
57- defer os .Remove (tempDir )
76+ defer func () {
77+ if err := os .Remove (tempDir ); err != nil {
78+ slog .Error ("failed to remove temporary folder/files" , slog .String ("reason" , err .Error ()))
79+ }
80+ }()
5881
5982 args := []string {"version" , "-m" }
6083 args = append (args , paths ... )
6184
85+ //nolint:gosec
86+ // the goBin variable was sanitized above
6287 cmd := exec .CommandContext (ctx , goBin , args ... )
6388 cmd .Dir = tempDir
6489 out , err := cmd .Output ()
6590 if err != nil {
66- if exitErr , ok := err .(* exec.ExitError ); ok {
91+ exitErr := & exec.ExitError {}
92+ if errors .As (err , & exitErr ) {
6793 return "" , fmt .Errorf ("error when running 'go version': %w - stderr: %s" , err , exitErr .Stderr )
6894 }
6995 return "" , fmt .Errorf ("error when running 'go version': %w" , err )
0 commit comments