Skip to content

Commit c828e3a

Browse files
Changed category to be considered 1 if no category is specified and no override detected
1 parent 5f25417 commit c828e3a

19 files changed

+67
-47
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@ Other fields are optional and can be seen in the example bellow of a file with a
298298
severity: High # severity, can only be one of [Critical, High, Medium, Low, Info]
299299
tags: # identifiers for the rule, tags can be used as values of --rule and --ignore-rule flags
300300
- api-key
301-
category: General # category of the rule, should be a string of type ruledefine.RuleCategory. Impacts cvss score
302-
scoreRuleType: 4 # can go from 4 to 0, 4 being most severe. For overrides, if Category is defined, ruleType also needs to be defined, or otherwise it will be considered 0. Impacts cvss score
301+
category: General # category of the rule, should be a string of type ruledefine.RuleCategory. Can be omitted in custom rule, but if omitted and ruleId matches a default rule, the category will take the value of the category of that defaultRule. Impacts cvss score
302+
scoreRuleType: 4 # can go from 1 to 4, 4 being most severe. If omitted in rule it will take the value of 1. Impacts cvss score
303303
disableValidation: false # if true, disables validity check for this rule, regardless of --validate flag
304304
deprecated: false # if true, the rule will not be used in the scan, regardless of --rule flag
305305
allowLists: # allowed values to ignore if matched

cmd/config_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"fmt"
45
"os"
56
"path/filepath"
67
"testing"
@@ -345,6 +346,12 @@ func TestCustomRulesFlag(t *testing.T) {
345346
expectedRules: nil,
346347
expectErrors: []error{errInvalidCustomRulesExtension},
347348
},
349+
{
350+
name: "Invalid rule type",
351+
customRulesFile: "testData/customRulesInvalidRuleType.json",
352+
expectedRules: nil,
353+
expectErrors: []error{fmt.Errorf("cannot unmarshal number -2 into Go struct field Rule.scoreRuleType of type uint8")},
354+
},
348355
}
349356

350357
for _, tt := range tests {

cmd/main_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func TestPreRun(t *testing.T) {
106106
" mockSeverity not one of ([Critical High Medium Low Info])"),
107107
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid category:" +
108108
" mockCategory not an acceptable category of type RuleCategory"),
109-
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid rule type: 10 not an acceptable uint8 value, maximum is 4"),
109+
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid rule type: 10 not an acceptable uint8 value, should be between 1 and 4"),
110110
},
111111
},
112112
{
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"ruleId": "db18ccf1-4fbf-49f6-aec1-939a2e5464c0",
4+
"ruleName": "mock-rule",
5+
"description": "Match passwords",
6+
"regex": "[A-Za-z0-9]{32}",
7+
"keywords": ["password", "pwd"],
8+
"entropy": 3.5,
9+
"path": "secrets/passwords.txt",
10+
"secretGroup": 1,
11+
"severity": "High",
12+
"tags": ["security", "credentials"],
13+
"category": "General",
14+
"scoreRuleType": -2
15+
}
16+
]

customrule_empty.json

Whitespace-only changes.

engine/engine.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -860,20 +860,17 @@ func CheckRulesRequiredFields(rulesToCheck []*ruledefine.Rule) error {
860860
}
861861
}
862862

863-
if rule.Category != "" {
864-
if _, ok := score.CategoryScoreMap[rule.Category]; !ok {
865-
invalidCategoryError := fmt.Errorf("%w: %s not an acceptable category of type RuleCategory",
866-
errInvalidCategory, rule.Category)
867-
err = errors.Join(err, buildCustomRuleError(i, rule, invalidCategoryError))
868-
}
863+
_, validCategory := score.CategoryScoreMap[rule.Category]
864+
if rule.Category != "" && !validCategory {
865+
invalidCategoryError := fmt.Errorf("%w: %s not an acceptable category of type RuleCategory",
866+
errInvalidCategory, rule.Category)
867+
err = errors.Join(err, buildCustomRuleError(i, rule, invalidCategoryError))
869868
}
870869

871-
if rule.ScoreRuleType != 0 {
872-
if rule.ScoreRuleType > score.RuleTypeMaxValue {
873-
invalidRuleTypeError := fmt.Errorf("%w: %d not an acceptable uint8 value, maximum is %d",
874-
errInvalidRuleType, rule.ScoreRuleType, score.RuleTypeMaxValue)
875-
err = errors.Join(err, buildCustomRuleError(i, rule, invalidRuleTypeError))
876-
}
870+
if rule.ScoreRuleType != 0 && rule.ScoreRuleType > score.RuleTypeMaxValue {
871+
invalidRuleTypeError := fmt.Errorf("%w: %d not an acceptable uint8 value, should be between 1 and 4",
872+
errInvalidRuleType, rule.ScoreRuleType)
873+
err = errors.Join(err, buildCustomRuleError(i, rule, invalidRuleTypeError))
877874
}
878875
}
879876

engine/rules/ruledefine/rule.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ type Rule struct {
8989
OldSeverity string `json:"oldSeverity" yaml:"oldSeverity"` //nolint:lll // fallback for when critical is not enabled, has no effect on open source
9090
AllowLists []*AllowList `json:"allowLists" yaml:"allowLists"`
9191
Tags []string `json:"tags" yaml:"tags"`
92-
Category RuleCategory `json:"category" yaml:"category"` // used for ASPM
93-
ScoreRuleType uint8 `json:"scoreRuleType" yaml:"scoreRuleType"` // used for ASPM
92+
Category RuleCategory `json:"category" yaml:"category"` // used for cvssScore
93+
ScoreRuleType uint8 `json:"scoreRuleType" yaml:"scoreRuleType"` // used for cvssScore
9494
DisableValidation bool `json:"disableValidation" yaml:"disableValidation"` ////nolint:lll // if true, validation checks will be skipped for this rule if any validation is possible
9595
Deprecated bool `json:"deprecated" yaml:"deprecated"`
9696
}

engine/score/score.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,12 @@ func getValidityScore(baseRiskScore float64, validationStatus secrets.Validation
105105
}
106106

107107
func GetBaseRiskScore(category ruledefine.RuleCategory, ruleType uint8) float64 {
108-
categoryScore := CategoryScoreMap[category]
108+
var categoryScore uint8
109+
var ok bool
110+
// default to the lowest score if category not found, should only happen on custom rules with undefined category
111+
if categoryScore, ok = CategoryScoreMap[category]; !ok {
112+
categoryScore = 1
113+
}
109114
return float64(categoryScore)*0.6 + float64(ruleType)*0.4
110115
}
111116

pkg/scan_test.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,14 @@ var customRules = []*ruledefine.Rule{
6767
Tags: []string{"custom"},
6868
Deprecated: true,
6969
},
70+
// missing category and scoreRuleType, which should be defaulted to 1
7071
{
71-
RuleID: "16be2682-51ee-44f5-82dc-695f4d1eda45",
72-
RuleName: "Mock-Custom-Rule",
73-
Description: "Rule that checks for a very specific string",
74-
Regex: `very_secret_value`,
75-
Severity: "Low",
76-
Tags: []string{"custom"},
77-
Category: "General",
78-
ScoreRuleType: 4,
72+
RuleID: "16be2682-51ee-44f5-82dc-695f4d1eda45",
73+
RuleName: "Mock-Custom-Rule",
74+
Description: "Rule that checks for a very specific string",
75+
Regex: `very_secret_value`,
76+
Severity: "Low",
77+
Tags: []string{"custom"},
7978
},
8079
{
8180
RuleID: "9f24ac30-9e04-4dc2-bc32-26da201f87e5",
@@ -596,7 +595,7 @@ func TestScanAndScanDynamicWithCustomRules(t *testing.T) {
596595
" mockSeverity not one of ([Critical High Medium Low Info])"),
597596
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid category:" +
598597
" mockCategory not an acceptable category of type RuleCategory"),
599-
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid rule type: 10 not an acceptable uint8 value, maximum is 4"),
598+
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid rule type: 10 not an acceptable uint8 value, should be between 1 and 4"),
600599
},
601600
},
602601
{

pkg/testData/expectedReports/customRules/defaultPlusAllCustomRules.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"source": "testData/secrets/generic-api-keys.txt",
99
"ruleId": "16be2682-51ee-44f5-82dc-695f4d1eda45",
1010
"ruleName": "Mock-Custom-Rule",
11-
"ruleCategory": "General",
11+
"ruleCategory": "",
1212
"startLine": 1,
1313
"endLine": 1,
1414
"lineContent": "mock_secret:=very_secret_value",
@@ -18,7 +18,7 @@
1818
"validationStatus": "Unknown",
1919
"ruleDescription": "Rule that checks for a very specific string",
2020
"severity": "Low",
21-
"cvssScore": 8.2
21+
"cvssScore": 1
2222
}
2323
],
2424
"5c27b555f2e14a8f4f9fdeda124f7332dd9835d9": [

0 commit comments

Comments
 (0)