From 84bc36f0718548a0ef0c17e792f0a7d1a40f92f6 Mon Sep 17 00:00:00 2001 From: Snider Date: Wed, 15 Apr 2026 21:53:52 +0100 Subject: [PATCH] Harden marketplace install error handling --- pkg/marketplace/marketplace.go | 18 +++++++++++++++++- pkg/marketplace/marketplace_test.go | 4 +++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pkg/marketplace/marketplace.go b/pkg/marketplace/marketplace.go index 78bfea78..57145b45 100644 --- a/pkg/marketplace/marketplace.go +++ b/pkg/marketplace/marketplace.go @@ -14,6 +14,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "unicode" @@ -44,6 +45,8 @@ type Installer struct { const maxManifestBytes = 1 << 20 +var credentialRedactionPattern = regexp.MustCompile(`(?i)\b([a-z][a-z0-9+.-]*://)([^@\s/]+)@`) + func (i Installer) FetchManifest(ctx context.Context, manifestURL string) (Manifest, error) { client := i.HTTPClient if client == nil { @@ -164,7 +167,7 @@ func (i Installer) Install(ctx context.Context, manifest Manifest) (string, erro } cmd := exec.CommandContext(ctx, binary, args...) if output, err := cmd.CombinedOutput(); err != nil { - return "", fmt.Errorf("git clone failed: %w: %s", err, strings.TrimSpace(string(output))) + return "", fmt.Errorf("git clone failed: %w: %s", err, sanitizeCommandOutput(output)) } if err := writeInstalledManifest(targetDir, manifest); err != nil { return "", err @@ -304,3 +307,16 @@ func writeInstalledManifest(targetDir string, manifest Manifest) error { } return os.WriteFile(filepath.Join(manifestDir, "marketplace.yaml"), data, 0o644) } + +func sanitizeCommandOutput(output []byte) string { + trimmed := strings.TrimSpace(string(output)) + if trimmed == "" { + return "command produced no output" + } + sanitized := credentialRedactionPattern.ReplaceAllString(trimmed, "$1[redacted]@") + const maxOutputChars = 512 + if len(sanitized) > maxOutputChars { + sanitized = sanitized[:maxOutputChars] + "..." + } + return sanitized +} diff --git a/pkg/marketplace/marketplace_test.go b/pkg/marketplace/marketplace_test.go index 246479b8..15ee8662 100644 --- a/pkg/marketplace/marketplace_test.go +++ b/pkg/marketplace/marketplace_test.go @@ -245,7 +245,7 @@ func TestMarketplace_Install_RejectsDashPrefixedRef(t *testing.T) { func TestMarketplace_Install_Ugly(t *testing.T) { scriptDir := t.TempDir() scriptPath := filepath.Join(scriptDir, "git") - require.NoError(t, os.WriteFile(scriptPath, []byte("#!/bin/sh\nexit 1\n"), 0o755)) + require.NoError(t, os.WriteFile(scriptPath, []byte("#!/bin/sh\nprintf '%s\\n' 'fatal: https://token:secret@example.com/repo.git' >&2\nexit 1\n"), 0o755)) installer := Installer{ GitBinary: scriptPath, @@ -258,6 +258,8 @@ func TestMarketplace_Install_Ugly(t *testing.T) { })) require.Error(t, err) assert.Contains(t, err.Error(), "git clone failed") + assert.NotContains(t, err.Error(), "secret") + assert.NotContains(t, err.Error(), "token:") } func TestMarketplace_Verify_Good(t *testing.T) {