diff --git a/internal/pkg/report/mask.go b/internal/pkg/report/mask.go index 286a3fc5..2ae19b8f 100644 --- a/internal/pkg/report/mask.go +++ b/internal/pkg/report/mask.go @@ -36,13 +36,16 @@ func (o *masker) add(secret string) { slices.SortFunc(o.multiLines, func(a, b []string) int { return cmp.Compare(len(b), len(a)) }) - } else { - o.lines = append(o.lines, lines[0]) - // make sure the longest secret are replaced first - slices.SortFunc(o.lines, func(a, b string) int { - return cmp.Compare(len(b), len(a)) - }) + // a multiline secret transformed into a single line by replacing + // newlines with \ followed by n must also be redacted + secret = strings.Join(lines, "\\n") } + + o.lines = append(o.lines, secret) + // make sure the longest secret are replaced first + slices.SortFunc(o.lines, func(a, b string) int { + return cmp.Compare(len(b), len(a)) + }) } func (o *masker) getReplacer() *strings.Replacer { diff --git a/internal/pkg/report/mask_test.go b/internal/pkg/report/mask_test.go index f6f332e4..8f26e698 100644 --- a/internal/pkg/report/mask_test.go +++ b/internal/pkg/report/mask_test.go @@ -41,6 +41,19 @@ SIX` out: "line before\n***\n***\n***\nline after\n", needMore: false, }, + { + // + // a multiline secret where newlines are represented + // as \ followed by n is masked + // + name: "MultilineTransformedIsMasked", + secrets: []string{ + multiLineOne, + }, + in: fmt.Sprintf("line before\n%[1]s\\nTWO\\nTHREE\nline after", lineOne), + out: "line before\n***\nline after\n", + needMore: false, + }, { // // in a multiline secret \r\n is equivalent to \n and does