diff --git a/cmd/pulse-agent/collector_lifecycle.go b/cmd/pulse-agent/collector_lifecycle.go index 3bfe4057f..ed2679b0d 100644 --- a/cmd/pulse-agent/collector_lifecycle.go +++ b/cmd/pulse-agent/collector_lifecycle.go @@ -13,6 +13,7 @@ import ( "time" "github.com/rcourtman/pulse-go-rewrite/internal/collectorlifecycle" + internalsecurity "github.com/rcourtman/pulse-go-rewrite/internal/securityutil" ) const ( @@ -84,7 +85,13 @@ func runCollectorLifecycleCommand(ctx context.Context, command string, args []st return errors.New("collector-download-installer requires --url and an absolute --output path") } info, err := os.Lstat(*outputPath) - if err != nil || !info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 || info.Mode().Perm()&0077 != 0 { + if err != nil || !info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 { + return errors.New("collector-download-installer output must be a pre-created private regular file") + } + // Unix privacy is expressed by owner-only mode bits. Windows ignores + // those bits, so apply the same protected-DACL validation used for + // lifecycle credentials instead of rejecting every Windows output. + if err := internalsecurity.ValidatePrivatePath(*outputPath, info); err != nil { return errors.New("collector-download-installer output must be a pre-created private regular file") } requestCtx, cancel := context.WithTimeout(ctx, 30*time.Second) diff --git a/cmd/pulse-agent/collector_lifecycle_test.go b/cmd/pulse-agent/collector_lifecycle_test.go index 8a14fe274..be8474962 100644 --- a/cmd/pulse-agent/collector_lifecycle_test.go +++ b/cmd/pulse-agent/collector_lifecycle_test.go @@ -123,6 +123,9 @@ func TestCollectorLifecycleCommandDownloadsInstallerThroughPublicTransport(t *te if err := os.WriteFile(outputPath, nil, 0600); err != nil { t.Fatal(err) } + if err := internalsecurity.HardenPrivatePath(outputPath, 0600); err != nil { + t.Fatalf("harden installer output: %v", err) + } var stdout, stderr bytes.Buffer err := runCollectorLifecycleCommand(context.Background(), collectorDownloadInstallerCommand, []string{ "--url", server.URL,