Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion internal/reflector/reflector.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ func (ExecRunner) Run(ctx context.Context, command string, args []string) (strin
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("run reflector command: %w: %s", err, truncate(stderr.String(), 2048))
redactedStderr := truncate(Redact(stderr.String()), 2048)
return "", fmt.Errorf("run reflector command: %w: %s", err, redactedStderr)
}
return stdout.String(), nil
}
Expand Down
20 changes: 20 additions & 0 deletions internal/reflector/reflector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,26 @@ func TestExecRunnerMarksReflectorActive(t *testing.T) {
}
}

func TestExecRunnerRedactsStderrOnFailure(t *testing.T) {
_, err := ExecRunner{}.Run(context.Background(), "sh", []string{
"-c",
"printf 'reflector failed with CUSTOM_SECRET=not-for-logs and API_KEY=test-api-key-value' >&2; exit 7",
})
if err == nil {
t.Fatal("Run returned nil error, want failure")
}

errorText := err.Error()
for _, leaked := range []string{"not-for-logs", "test-api-key-value"} {
if strings.Contains(errorText, leaked) {
t.Fatalf("error leaked %q: %s", leaked, errorText)
}
}
if !strings.Contains(errorText, "CUSTOM_SECRET=<redacted>") || !strings.Contains(errorText, "API_KEY=<redacted>") {
t.Fatalf("error did not preserve redacted stderr context: %s", errorText)
}
}

type fakeRunner struct {
command string
args []string
Expand Down