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
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,8 @@ Other fields are optional and can be seen in the example bellow of a file with a
severity: High # severity, can only be one of [Critical, High, Medium, Low, Info]
tags: # identifiers for the rule, tags can be used as values of --rule and --ignore-rule flags
- api-key
scoreParameters: # scoreParameters can be omitted for overrides, in which case the respective default rule scoreParameters will be considered
category: General # category of the rule, should be a string of type ruledefine.RuleCategory. Impacts cvss score
ruleType: 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
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
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
disableValidation: false # if true, disables validity check for this rule, regardless of --validate flag
deprecated: false # if true, the rule will not be used in the scan, regardless of --rule flag
allowLists: # allowed values to ignore if matched
Expand Down
15 changes: 10 additions & 5 deletions cmd/config_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"fmt"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -297,11 +298,9 @@ func TestCustomRulesFlag(t *testing.T) {
StopWords: []string{"example", "sample"},
},
},
Tags: []string{"security", "credentials"},
ScoreParameters: ruledefine.ScoreParameters{
Category: "General",
RuleType: 2,
},
Tags: []string{"security", "credentials"},
Category: "General",
ScoreRuleType: 2,
DisableValidation: true,
Deprecated: true,
},
Expand Down Expand Up @@ -347,6 +346,12 @@ func TestCustomRulesFlag(t *testing.T) {
expectedRules: nil,
expectErrors: []error{errInvalidCustomRulesExtension},
},
{
name: "Invalid rule type",
customRulesFile: "testData/customRulesInvalidRuleType.json",
expectedRules: nil,
expectErrors: []error{fmt.Errorf("cannot unmarshal number -2 into Go struct field Rule.scoreRuleType of type uint8")},
},
}

for _, tt := range tests {
Expand Down
18 changes: 8 additions & 10 deletions cmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,13 @@ func TestPreRun(t *testing.T) {
engineConfigVar: engine.EngineConfig{
CustomRules: []*ruledefine.Rule{
{
RuleID: "db18ccf1-4fbf-49f6-aec1-939a2e5464c0",
RuleName: "mock-rule",
Description: "Match passwords",
Regex: "[A-Za-z0-9]{32})",
Severity: "mockSeverity",
ScoreParameters: ruledefine.ScoreParameters{
Category: "mockCategory",
RuleType: 10,
},
RuleID: "db18ccf1-4fbf-49f6-aec1-939a2e5464c0",
RuleName: "mock-rule",
Description: "Match passwords",
Regex: "[A-Za-z0-9]{32})",
Severity: "mockSeverity",
Category: "mockCategory",
ScoreRuleType: 10,
},
{
RuleID: "b47a1995-6572-41bb-b01d-d215b43ab089",
Expand All @@ -108,7 +106,7 @@ func TestPreRun(t *testing.T) {
" mockSeverity not one of ([Critical High Medium Low Info])"),
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid category:" +
" mockCategory not an acceptable category of type RuleCategory"),
fmt.Errorf("rule#0;RuleID-db18ccf1-4fbf-49f6-aec1-939a2e5464c0: invalid rule type: 10 not an acceptable uint8 value, maximum is 4"),
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"),
},
},
{
Expand Down
16 changes: 16 additions & 0 deletions cmd/testData/customRulesInvalidRuleType.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"ruleId": "db18ccf1-4fbf-49f6-aec1-939a2e5464c0",
"ruleName": "mock-rule",
"description": "Match passwords",
"regex": "[A-Za-z0-9]{32}",
"keywords": ["password", "pwd"],
"entropy": 3.5,
"path": "secrets/passwords.txt",
"secretGroup": 1,
"severity": "High",
"tags": ["security", "credentials"],
"category": "General",
"scoreRuleType": -2
}
]
6 changes: 2 additions & 4 deletions cmd/testData/customRulesValid.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@
}
],
"tags": ["security", "credentials"],
"scoreParameters": {
"category": "General",
"ruleType": 2
},
"category": "General",
"scoreRuleType": 2,
"disableValidation": true,
"deprecated": true
},
Expand Down
5 changes: 2 additions & 3 deletions cmd/testData/customRulesValid.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@
tags:
- security
- credentials
scoreParameters:
category: General
ruleType: 2
category: General
scoreRuleType: 2
disableValidation: true
deprecated: true

Expand Down
23 changes: 10 additions & 13 deletions engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ func (e *Engine) addExtrasToSecret(secret *secrets.Secret) {
// add general extra data
extra.Mtxs.Lock(secret.ID)
secret.RuleName = e.rules[secret.RuleID].RuleName
secret.RuleCategory = string(e.rules[secret.RuleID].ScoreParameters.Category)
secret.RuleCategory = string(e.rules[secret.RuleID].Category)
extra.Mtxs.Unlock(secret.ID)

// add rule specific extra data
Expand Down Expand Up @@ -869,20 +869,17 @@ func CheckRulesRequiredFields(rulesToCheck []*ruledefine.Rule) error {
}
}

if rule.ScoreParameters.Category != "" {
if _, ok := score.CategoryScoreMap[rule.ScoreParameters.Category]; !ok {
invalidCategoryError := fmt.Errorf("%w: %s not an acceptable category of type RuleCategory",
errInvalidCategory, rule.ScoreParameters.Category)
err = errors.Join(err, buildCustomRuleError(i, rule, invalidCategoryError))
}
_, validCategory := score.CategoryScoreMap[rule.Category]
if rule.Category != "" && !validCategory {
invalidCategoryError := fmt.Errorf("%w: %s not an acceptable category of type RuleCategory",
errInvalidCategory, rule.Category)
err = errors.Join(err, buildCustomRuleError(i, rule, invalidCategoryError))
}

if rule.ScoreParameters.RuleType != 0 {
if rule.ScoreParameters.RuleType > score.RuleTypeMaxValue {
invalidRuleTypeError := fmt.Errorf("%w: %d not an acceptable uint8 value, maximum is %d",
errInvalidRuleType, rule.ScoreParameters.RuleType, score.RuleTypeMaxValue)
err = errors.Join(err, buildCustomRuleError(i, rule, invalidRuleTypeError))
}
if rule.ScoreRuleType != 0 && rule.ScoreRuleType > score.RuleTypeMaxValue {
invalidRuleTypeError := fmt.Errorf("%w: %d not an acceptable uint8 value, should be between 1 and 4",
errInvalidRuleType, rule.ScoreRuleType)
err = errors.Join(err, buildCustomRuleError(i, rule, invalidRuleTypeError))
}
}

Expand Down
9 changes: 5 additions & 4 deletions engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ func TestProcessSecretsExtras(t *testing.T) {
ID: "mockId",
RuleID: ruledefine.JWT().RuleID,
RuleName: ruledefine.JWT().RuleName,
RuleCategory: string(ruledefine.JWT().ScoreParameters.Category),
RuleCategory: string(ruledefine.JWT().Category),
Value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtb2NrU3ViMSIsIm5hbWUiOiJtb2NrTmFtZTEifQ.dummysignature1",
ExtraDetails: map[string]interface{}{
"secretDetails": map[string]interface{}{
Expand All @@ -1090,7 +1090,7 @@ func TestProcessSecretsExtras(t *testing.T) {
ID: "mockId2",
RuleID: ruledefine.JWT().RuleID,
RuleName: ruledefine.JWT().RuleName,
RuleCategory: string(ruledefine.JWT().ScoreParameters.Category),
RuleCategory: string(ruledefine.JWT().Category),
Value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtb2NrU3ViMiIsIm5hbWUiOiJtb2NrTmFtZTIifQ.dummysignature2",
ExtraDetails: map[string]interface{}{
"secretDetails": map[string]interface{}{
Expand All @@ -1103,7 +1103,7 @@ func TestProcessSecretsExtras(t *testing.T) {
ID: "mockId3",
RuleID: ruledefine.HubSpot().RuleID,
RuleName: ruledefine.HubSpot().RuleName,
RuleCategory: string(ruledefine.HubSpot().ScoreParameters.Category),
RuleCategory: string(ruledefine.HubSpot().Category),
Value: "mockValue",
},
},
Expand Down Expand Up @@ -1184,7 +1184,8 @@ func TestProcessEvaluationWithValidation(t *testing.T) {
RuleName: ruledefine.GitHubPat().RuleName,
Regex: ruledefine.GitHubPat().Regex,
Severity: ruledefine.GitHubPat().Severity,
ScoreParameters: ruledefine.GitlabPat().ScoreParameters,
Category: ruledefine.GitHubPat().Category,
ScoreRuleType: ruledefine.GitHubPat().ScoreRuleType,
DisableValidation: true,
},
},
Expand Down
19 changes: 10 additions & 9 deletions engine/rules/ruledefine/1password_secret_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ var onePasswordSecretKeyRegex = regexp.MustCompile(
func OnePasswordSecretKey() *Rule {
// define rule
return &Rule{
RuleID: "4068d686-6833-4976-8f4a-5397e75c7fc5",
Description: "Uncovered a possible 1Password secret key, potentially compromising access to secrets in vaults.",
RuleName: "1Password-Secret-Key",
Regex: onePasswordSecretKeyRegex,
Entropy: 3.8,
Keywords: []string{"A3-"},
Severity: "High",
Tags: []string{TagPrivateKey},
ScoreParameters: ScoreParameters{Category: CategoryAuthenticationAndAuthorization, RuleType: 4},
RuleID: "4068d686-6833-4976-8f4a-5397e75c7fc5",
Description: "Uncovered a possible 1Password secret key, potentially compromising access to secrets in vaults.",
RuleName: "1Password-Secret-Key",
Regex: onePasswordSecretKeyRegex,
Entropy: 3.8,
Keywords: []string{"A3-"},
Severity: "High",
Tags: []string{TagPrivateKey},
Category: CategoryAuthenticationAndAuthorization,
ScoreRuleType: 4,
}
}
19 changes: 10 additions & 9 deletions engine/rules/ruledefine/1password_service_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ var onePasswordServiceAccountTokenRegex = regexp.MustCompile(`ops_eyJ[a-zA-Z0-9+
func OnePasswordServiceAccountToken() *Rule {
// define rule
return &Rule{
RuleID: "0ea85582-ea27-4f6f-b5f0-db3c4a75a07e",
RuleName: "1Password-Service-Account-Token",
Description: "Uncovered a possible 1Password service account token, potentially compromising access to secrets in vaults.",
Regex: onePasswordServiceAccountTokenRegex,
Entropy: 4,
Keywords: []string{"ops_"},
Severity: "High",
Tags: []string{TagAccessToken},
ScoreParameters: ScoreParameters{Category: CategoryAuthenticationAndAuthorization, RuleType: 4},
RuleID: "0ea85582-ea27-4f6f-b5f0-db3c4a75a07e",
RuleName: "1Password-Service-Account-Token",
Description: "Uncovered a possible 1Password service account token, potentially compromising access to secrets in vaults.",
Regex: onePasswordServiceAccountTokenRegex,
Entropy: 4,
Keywords: []string{"ops_"},
Severity: "High",
Tags: []string{TagAccessToken},
Category: CategoryAuthenticationAndAuthorization,
ScoreRuleType: 4,
}
}
13 changes: 7 additions & 6 deletions engine/rules/ruledefine/adafruit.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ func AdafruitAPIKey() *Rule {
RuleID: "c29ea920-52c4-4366-9e75-1574e286d1d7",
Description: "Identified a potential Adafruit API Key," +
" which could lead to unauthorized access to Adafruit services and sensitive data exposure.",
RuleName: "Adafruit-Api-Key",
Regex: adafruitAPIKeyRegex,
Keywords: []string{"adafruit"},
Severity: "High",
Tags: []string{TagApiKey},
ScoreParameters: ScoreParameters{Category: CategoryIoTPlatform, RuleType: 4},
RuleName: "Adafruit-Api-Key",
Regex: adafruitAPIKeyRegex,
Keywords: []string{"adafruit"},
Severity: "High",
Tags: []string{TagApiKey},
Category: CategoryIoTPlatform,
ScoreRuleType: 4,
}
}
13 changes: 7 additions & 6 deletions engine/rules/ruledefine/adobe_client_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ func AdobeClientID() *Rule {
RuleName: "Adobe-Client-Id",
Description: "Detected a pattern that resembles an Adobe OAuth Web Client ID," +
" posing a risk of compromised Adobe integrations and data breaches.",
Regex: adobeClientIDRegex,
Entropy: 2,
Keywords: []string{"adobe"},
Severity: "High",
Tags: []string{TagClientId},
ScoreParameters: ScoreParameters{Category: CategorySaaS, RuleType: 1},
Regex: adobeClientIDRegex,
Entropy: 2,
Keywords: []string{"adobe"},
Severity: "High",
Tags: []string{TagClientId},
Category: CategorySaaS,
ScoreRuleType: 1,
}
}
13 changes: 7 additions & 6 deletions engine/rules/ruledefine/adobe_client_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ func AdobeClientSecret() *Rule {
RuleName: "Adobe-Client-Secret",
Description: "Discovered a potential Adobe Client Secret, which," +
" if exposed, could allow unauthorized Adobe service access and data manipulation.",
Regex: adobeClientSecretRegex,
Entropy: 2,
Keywords: []string{"p8e-"},
Severity: "High",
Tags: []string{TagClientSecret},
ScoreParameters: ScoreParameters{Category: CategorySaaS, RuleType: 4},
Regex: adobeClientSecretRegex,
Entropy: 2,
Keywords: []string{"p8e-"},
Severity: "High",
Tags: []string{TagClientSecret},
Category: CategorySaaS,
ScoreRuleType: 4,
}
}
13 changes: 7 additions & 6 deletions engine/rules/ruledefine/age.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ func AgeSecretKey() *Rule {
RuleID: "5137d287-beb3-4ac4-844a-952618a69c47",
Description: "Discovered a potential Age encryption tool secret key," +
" risking data decryption and unauthorized access to sensitive information.",
RuleName: "Age-Secret-Key",
Regex: ageSecretKeyRegex,
Keywords: []string{"AGE-SECRET-KEY-1"},
Severity: "High",
Tags: []string{TagSecretKey},
ScoreParameters: ScoreParameters{Category: CategoryGeneralOrUnknown, RuleType: 4},
RuleName: "Age-Secret-Key",
Regex: ageSecretKeyRegex,
Keywords: []string{"AGE-SECRET-KEY-1"},
Severity: "High",
Tags: []string{TagSecretKey},
Category: CategoryGeneralOrUnknown,
ScoreRuleType: 4,
}
}
13 changes: 7 additions & 6 deletions engine/rules/ruledefine/airtable.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ func Airtable() *Rule {
RuleID: "6869a35b-dfad-439d-b285-3b26a4469224",
Description: "Uncovered a possible Airtable API Key," +
" potentially compromising database access and leading to data leakage or alteration.",
RuleName: "Airtable-Api-Key",
Regex: airtableRegex,
Keywords: []string{"airtable"},
Severity: "High",
Tags: []string{TagApiKey},
ScoreParameters: ScoreParameters{Category: CategoryDatabaseAsAService, RuleType: 4},
RuleName: "Airtable-Api-Key",
Regex: airtableRegex,
Keywords: []string{"airtable"},
Severity: "High",
Tags: []string{TagApiKey},
Category: CategoryDatabaseAsAService,
ScoreRuleType: 4,
}
}
13 changes: 7 additions & 6 deletions engine/rules/ruledefine/algolia.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ func AlgoliaApiKey() *Rule {
RuleID: "3e3052a1-5be8-4ed8-90a3-f50b94c96fe5",
Description: "Identified an Algolia API Key," +
" which could result in unauthorized search operations and data exposure on Algolia-managed platforms.",
RuleName: "Algolia-Api-Key",
Regex: algoliaRegex,
Keywords: []string{"algolia"},
Severity: "High",
Tags: []string{TagApiKey},
ScoreParameters: ScoreParameters{Category: CategorySearchService, RuleType: 4},
RuleName: "Algolia-Api-Key",
Regex: algoliaRegex,
Keywords: []string{"algolia"},
Severity: "High",
Tags: []string{TagApiKey},
Category: CategorySearchService,
ScoreRuleType: 4,
}
}
13 changes: 7 additions & 6 deletions engine/rules/ruledefine/alibaba_access_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ func AlibabaAccessKey() *Rule {
RuleName: "Alibaba-Access-Key-Id",
Description: "Detected an Alibaba Cloud AccessKey ID," +
" posing a risk of unauthorized cloud resource access and potential data compromise.",
Regex: alibabaAccessKeyRegex,
Entropy: 2,
Keywords: []string{"LTAI"},
Severity: "High",
Tags: []string{TagAccessKey, TagAccessId},
ScoreParameters: ScoreParameters{Category: CategoryCloudPlatform, RuleType: 1},
Regex: alibabaAccessKeyRegex,
Entropy: 2,
Keywords: []string{"LTAI"},
Severity: "High",
Tags: []string{TagAccessKey, TagAccessId},
Category: CategoryCloudPlatform,
ScoreRuleType: 1,
}
}
Loading
Loading