diff --git a/internal/outputer/formatter/formatter_human.go b/internal/outputer/formatter/formatter_human.go index 3212d66d..905e394b 100644 --- a/internal/outputer/formatter/formatter_human.go +++ b/internal/outputer/formatter/formatter_human.go @@ -146,7 +146,7 @@ func (hp humanPolicyFormatter) FormatText(depth int, format string, args ...inte return indentMultiline(depth, fmt.Sprintf(format, args...)) } -func (hp humanPolicyFormatter) FormatList(depth int, title string, list []string, ordered bool) string { +func (hp humanPolicyFormatter) FormatList(depth int, title string, list []string, ordered bool, addListPrefix bool) string { if len(list) == 0 { return "" } diff --git a/internal/outputer/formatter/formatter_markdown.go b/internal/outputer/formatter/formatter_markdown.go index 8a6675da..e8394f66 100644 --- a/internal/outputer/formatter/formatter_markdown.go +++ b/internal/outputer/formatter/formatter_markdown.go @@ -3,6 +3,7 @@ package formatter import ( "bytes" "fmt" + "regexp" "strings" "github.com/Legit-Labs/legitify/internal/common/severity" @@ -174,19 +175,43 @@ func (mp markdownPolicyFormatter) FormatText(depth int, format string, args ...i return indentMultilineSpecial(depth, fmt.Sprintf(format, args...), mp.Indent(1), mp.Linebreak()) } -func (mp markdownPolicyFormatter) FormatList(depth int, title string, list []string, ordered bool) string { +func isMarkdownListItem(s string) bool { + unorderedPattern := `^[\-\*\+] ` + orderedPattern := `^\d+\.\s` + + unorderedRegex, err := regexp.Compile(unorderedPattern) + if err != nil { + return false + } + + orderedRegex, err := regexp.Compile(orderedPattern) + if err != nil { + return false + } + + return unorderedRegex.MatchString(s) || orderedRegex.MatchString(s) +} + +func (mp markdownPolicyFormatter) FormatList(depth int, title string, list []string, ordered bool, addListPrefix bool) string { if len(list) == 0 { return "" } var sb strings.Builder bullet := "-" - sb.WriteString(mp.FormatText(depth, "%s\n", title)) + sb.WriteString(mp.FormatText(depth, "%s\n\n", title)) for i, step := range list { - if ordered { - bullet = fmt.Sprintf("%d.", i+1) + if addListPrefix { + if ordered { + bullet = fmt.Sprintf("%d.", i+1) + } + sb.WriteString(mp.FormatText(depth, "%s %s\n", bullet, step)) + } else { + sb.WriteString(mp.FormatText(depth, "%s\n", step)) + if !isMarkdownListItem(step) { + sb.WriteString(mp.FormatText(depth, "\n")) + } } - sb.WriteString(mp.FormatText(depth, "%s %s\n", bullet, step)) } return sb.String() diff --git a/internal/outputer/formatter/formatter_sarif.go b/internal/outputer/formatter/formatter_sarif.go index 46fade7c..372b04a1 100644 --- a/internal/outputer/formatter/formatter_sarif.go +++ b/internal/outputer/formatter/formatter_sarif.go @@ -217,7 +217,7 @@ func (sp sarifPolicyFormatter) FormatText(depth int, format string, args ...inte return indentMultilineSpecial(depth, fmt.Sprintf(format, args...), sp.Indent(1), sp.Linebreak()) } -func (sp sarifPolicyFormatter) FormatList(depth int, title string, list []string, ordered bool) string { +func (sp sarifPolicyFormatter) FormatList(depth int, title string, list []string, ordered bool, addListPrefix bool) string { if len(list) == 0 { return "" } diff --git a/internal/outputer/formatter/policies_content.go b/internal/outputer/formatter/policies_content.go index a2b14320..f8ea1123 100644 --- a/internal/outputer/formatter/policies_content.go +++ b/internal/outputer/formatter/policies_content.go @@ -14,7 +14,7 @@ type policiesFormatter interface { FormatTitle(title string, severity string) string FormatSubtitle(title string) string FormatText(depth int, format string, args ...interface{}) string - FormatList(depth int, title string, list []string, ordered bool) string + FormatList(depth int, title string, list []string, ordered bool, addListPrefix bool) string Linebreak() string Separator() string Indent(depth int) string @@ -94,9 +94,9 @@ func (pc *policiesContent) writeLineBreak() { pc.writeLine("") } -func (pc *policiesContent) writeList(title string, list []string, ordered bool) { +func (pc *policiesContent) writeList(title string, list []string, ordered bool, addListPrefix bool) { title = fmt.Sprintf("%s:", pc.bold(title)) - pc.sb.WriteString(pc.pf.FormatList(pc.depth, title, list, ordered)) + pc.sb.WriteString(pc.pf.FormatList(pc.depth, title, list, ordered, addListPrefix)) } func (pc *policiesContent) writeKeyval(key string, val string) { @@ -114,10 +114,10 @@ func (pc *policiesContent) writePolicyInfo(policyName string, policyInfo scheme. pc.writeKeyval("Severity", coloredSeverity) pc.writeLineBreak() - pc.writeList("Threat", policyInfo.Threat, false) + pc.writeList("Threat", policyInfo.Threat, false, true) pc.writeLineBreak() - pc.writeList("Remediation Steps", policyInfo.RemediationSteps, true) + pc.writeList("Remediation Steps", policyInfo.RemediationSteps, false, false) } func (pc *policiesContent) bold(text interface{}) string { @@ -146,7 +146,7 @@ func (pc *policiesContent) writeAux(aux *orderedmap.OrderedMap) { return } - pc.writeList("Auxiliary Info", pc.auxAsList(aux), false) + pc.writeList("Auxiliary Info", pc.auxAsList(aux), false, true) } func (pc *policiesContent) auxAsList(m *orderedmap.OrderedMap) []string { diff --git a/policies/github/organization.rego b/policies/github/organization.rego index 0dd09a90..d5f5cc8a 100644 --- a/policies/github/organization.rego +++ b/policies/github/organization.rego @@ -156,12 +156,12 @@ organization_not_using_single_sign_on := false { # custom: # requiredEnrichers: [secretsList] # remediationSteps: -# - Enter your organization's landing page -# - Go to the settings tab -# - Under the 'Security' title on the left, choose 'Secrets and variables' -# - Click 'Actions' -# - Sort secrets by 'Last Updated' -# - Regenerate every secret older than one year and add the new value to GitHub's secret manager +# - 1. Enter your organization's landing page +# - 2. Go to the settings tab +# - 3. Under the 'Security' title on the left, choose 'Secrets and variables' +# - 4. Click 'Actions' +# - 5. Sort secrets by 'Last Updated' +# - 6. Regenerate every secret older than one year and add the new value to GitHub's secret manager # severity: MEDIUM # requiredScopes: [admin:org, repo] # threat: Sensitive data may have been inadvertently made public in the past, and an attacker who holds this data may gain access to your current CI and services. In addition, there may be old or unnecessary tokens that have not been inspected and can be used to access sensitive information.