diff --git a/storage/download.go b/storage/download.go index 6a5326f..d7348e9 100644 --- a/storage/download.go +++ b/storage/download.go @@ -11,28 +11,31 @@ import ( "math" "net/http" "os" + "path/filepath" "github.com/dustin/go-humanize" "github.com/pkg/errors" ) func (s *Storage) download(ctx context.Context, url string, hash []byte, out string, applyReaderMiddleware func(io.Reader) io.Reader) error { + outClean := filepath.Clean(out) + var created, success bool defer func() { if created && !success { - _ = os.Remove(out) + _ = os.Remove(outClean) } }() - _, err := os.Stat(out) + _, err := os.Stat(outClean) if err == nil { return errors.Wrap(err, "file already exists") } else if !errors.Is(err, os.ErrNotExist) { return errors.Wrap(err, "stat out path") } - f, err := os.OpenFile(out, os.O_CREATE|os.O_WRONLY, 0400) + f, err := os.OpenFile(outClean, os.O_CREATE|os.O_WRONLY, 0400) if err != nil { return errors.Wrap(err, "open file") } @@ -46,7 +49,7 @@ func (s *Storage) download(ctx context.Context, url string, hash []byte, out str return errors.Wrap(err, "create new http get request") } - s.logger.Info("Starting to download file", "from", url, "to", out) + s.logger.Info("Starting to download file", "from", url, "to", outClean) resp, err := http.DefaultClient.Do(req) if err != nil { @@ -71,7 +74,7 @@ func (s *Storage) download(ctx context.Context, url string, hash []byte, out str percent = float64(downloaded) / float64(knownSize) } - lg := s.logger.With("out", out, "done", humanize.Bytes(uint64(downloaded))) + lg := s.logger.With("out", outClean, "done", humanize.Bytes(uint64(downloaded))) if percent != 0 { lg.Info("Downloading file", "percent", math.Round(percent*100*100)/100) } else { @@ -82,7 +85,7 @@ func (s *Storage) download(ctx context.Context, url string, hash []byte, out str return errors.Wrap(err, "copy resp to file") } - s.logger.Info("Successfully downloaded file", "from", url, "to", out, "out-size", humanize.Bytes(uint64(n))) + s.logger.Info("Successfully downloaded file", "from", url, "to", outClean, "out-size", humanize.Bytes(uint64(n))) success = true diff --git a/storage/hash.go b/storage/hash.go index 6414a69..923a75b 100644 --- a/storage/hash.go +++ b/storage/hash.go @@ -7,12 +7,15 @@ import ( "fmt" "io" "os" + "path/filepath" "github.com/pkg/errors" ) func validateFileHash(path string, hash []byte) error { - f, err := os.OpenFile(path, os.O_RDONLY, 0400) + pathClean := filepath.Clean(path) + + f, err := os.OpenFile(pathClean, os.O_RDONLY, 0400) if err != nil { return errors.Wrap(err, "open file") } @@ -38,7 +41,7 @@ func validateFileHash(path string, hash []byte) error { sum := h.Sum(nil) if !bytes.Equal(sum, hash) { - return fmt.Errorf("hash mismatch: want '%v', have '%v' (path '%v')", hex.EncodeToString(hash), hex.EncodeToString(sum), path) + return fmt.Errorf("hash mismatch: want '%v', have '%v' (path '%v')", hex.EncodeToString(hash), hex.EncodeToString(sum), pathClean) } return nil diff --git a/storage/nettap.go b/storage/nettap.go index a819b80..19f4e60 100644 --- a/storage/nettap.go +++ b/storage/nettap.go @@ -65,7 +65,7 @@ func (s *Storage) ListNetTapAllocations() ([]nettap.Alloc, error) { for _, entry := range dirEntries { if strings.HasPrefix(entry.Name(), tapAllocPrefix) { - entryPath := filepath.Join(s.path, entry.Name()) + entryPath := filepath.Clean(filepath.Join(s.path, entry.Name())) tapName := strings.TrimPrefix(entry.Name(), tapAllocPrefix) err := nettap.ValidateTapName(tapName) diff --git a/vm/vm.go b/vm/vm.go index a7e1a7e..e24f8e3 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -153,7 +153,7 @@ func NewVM(logger *slog.Logger, cfg Config) (*VM, error) { sysRead, userWrite := io.Pipe() userRead, sysWrite := io.Pipe() - cmd := exec.Command(baseCmd, encodedCmdArgs...) + cmd := exec.Command(baseCmd, encodedCmdArgs...) //#nosec G204 // I know, it's generally a bad idea to include variables into shell commands, but QEMU unfortunately does not accept anything else. cmd.Stdin = sysRead cmd.Stdout = sysWrite