Skip to content

Commit

Permalink
fix(misconf): don't shift ignore rule related to code
Browse files Browse the repository at this point in the history
  • Loading branch information
nikpivkin committed May 16, 2024
1 parent 88702cf commit ed703f7
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 21 deletions.
41 changes: 25 additions & 16 deletions pkg/iac/ignore/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

Check failure on line 7 in pkg/iac/ignore/parse.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/aquasecurity/) -s blank -s dot (gci)
"github.com/aquasecurity/trivy/pkg/iac/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/samber/lo"

Check failure on line 10 in pkg/iac/ignore/parse.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/aquasecurity/) -s blank -s dot (gci)
)

// RuleSectionParser defines the interface for parsing ignore rules.
Expand Down Expand Up @@ -36,23 +37,34 @@ func Parse(src, path string, parsers ...RuleSectionParser) Rules {
func parseLine(line string, rng types.Range, parsers []RuleSectionParser) []Rule {
var rules []Rule

sections := strings.Split(strings.TrimSpace(line), " ")
for _, section := range sections {
section := strings.TrimSpace(section)
section = strings.TrimLeftFunc(section, func(r rune) bool {
parts := strings.Split(strings.TrimSpace(line), " ")
parts = lo.FilterMap(parts, func(part string, _ int) (string, bool) {
part = strings.TrimSpace(part)
part = strings.TrimLeftFunc(part, func(r rune) bool {
return r == '#' || r == '/' || r == '*'
})

section, exists := hasIgnoreRulePrefix(section)
return part, len(part) > 0

Check failure on line 47 in pkg/iac/ignore/parse.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

emptyStringTest: replace `len(part) > 0` with `part != ""` (gocritic)

Check failure on line 47 in pkg/iac/ignore/parse.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

emptyStringTest: replace `len(part) > 0` with `part != ""` (gocritic)
})

for i, part := range parts {
part, exists := hasIgnoreRulePrefix(part)
if !exists {
continue
}

rule, err := parseComment(section, rng, parsers)
sections, err := parseRuleSections(part, rng, parsers)
if err != nil {
log.Debug("Failed to parse rule", log.String("range", rng.String()), log.Err(err))
continue
}

rule := Rule{
rng: rng,
isStartLine: i == 0 || (len(rules) > 0 && rules[0].isStartLine),
sections: sections,
}

rules = append(rules, rule)
}

Expand All @@ -72,11 +84,8 @@ func hasIgnoreRulePrefix(s string) (string, bool) {
return "", false
}

func parseComment(input string, rng types.Range, parsers []RuleSectionParser) (Rule, error) {
rule := Rule{
rng: rng,
sections: make(map[string]any),
}
func parseRuleSections(input string, rng types.Range, parsers []RuleSectionParser) (map[string]any, error) {
sections := make(map[string]any)

parsers = append(parsers, &expiryDateParser{
rng: rng,
Expand All @@ -93,7 +102,7 @@ func parseComment(input string, rng types.Range, parsers []RuleSectionParser) (R
StringMatchParser{SectionKey: "id"},
}
if idParser.Parse(val) {
rule.sections[idParser.Key()] = idParser.Param()
sections[idParser.Key()] = idParser.Param()
}
}

Expand All @@ -103,16 +112,16 @@ func parseComment(input string, rng types.Range, parsers []RuleSectionParser) (R
}

if parser.Parse(val) {
rule.sections[parser.Key()] = parser.Param()
sections[parser.Key()] = parser.Param()
}
}
}

if _, exists := rule.sections["id"]; !exists {
return Rule{}, errors.New("rule section with the `ignore` key is required")
if _, exists := sections["id"]; !exists {
return nil, errors.New("rule section with the `ignore` key is required")
}

return rule, nil
return sections, nil
}

type StringMatchParser struct {
Expand Down
16 changes: 11 additions & 5 deletions pkg/iac/ignore/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ func (r Rules) shift() {
)

for i := len(r) - 1; i > 0; i-- {
currentIgnore, nextIgnore := r[i], r[i-1]
currentRule, prevRule := r[i], r[i-1]

if !prevRule.isStartLine {
continue
}

if currentRange == nil {
currentRange = &currentIgnore.rng
currentRange = &currentRule.rng
}
if nextIgnore.rng.GetStartLine()+1+offset == currentIgnore.rng.GetStartLine() {
if prevRule.rng.GetStartLine()+1+offset == currentRule.rng.GetStartLine() {
r[i-1].rng = *currentRange
offset++
} else {
Expand All @@ -46,8 +51,9 @@ func (r Rules) shift() {

// Rule represents a rule for ignoring vulnerabilities.
type Rule struct {
rng types.Range
sections map[string]any
rng types.Range
isStartLine bool
sections map[string]any
}

func (r Rule) ignore(m types.Metadata, ids []string, ignorers map[string]Ignorer) bool {
Expand Down
35 changes: 35 additions & 0 deletions pkg/iac/ignore/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,41 @@ func TestRules_Ignore(t *testing.T) {
},
shouldIgnore: false,
},
{
name: "multiple ignore rules on the same line",
src: `test #trivy:ignore:rule-1
test #trivy:ignore:rule-2
`,
args: args{
metadata: metadataWithLine(filename, 1),
ids: []string{"rule-1"},
},
shouldIgnore: true,
},
{
name: "multiple ignore rules on the same line",
src: `# trivy:ignore:rule-1
# trivy:ignore:rule-2
test #trivy:ignore:rule-3
`,
args: args{
metadata: metadataWithLine(filename, 3),
ids: []string{"rule-1"},
},
shouldIgnore: true,
},
{
name: "multiple ignore rules on the same line",
src: `# trivy:ignore:rule-1 # trivy:ignore:rule-2
# trivy:ignore:rule-3
test #trivy:ignore:rule-4
`,
args: args{
metadata: metadataWithLine(filename, 3),
ids: []string{"rule-2"},
},
shouldIgnore: true,
},
}

for _, tt := range tests {
Expand Down

0 comments on commit ed703f7

Please sign in to comment.