Просмотр исходного кода

feat(generic-api-key): tune false positives (#1606)

Richard Gomez 1 год назад
Родитель
Сommit
961f2e674f
2 измененных файлов с 100 добавлено и 42 удалено
  1. 93 35
      cmd/generate/config/rules/generic.go
  2. 7 7
      config/gitleaks.toml

+ 93 - 35
cmd/generate/config/rules/generic.go

@@ -13,28 +13,28 @@ func GenericCredential() *config.Rule {
 		RuleID:      "generic-api-key",
 		Description: "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
 		Regex: utils.GenerateSemiGenericRegex([]string{
-			"key",
-			"api",
-			"token",
-			"secret",
+			"access",
+			"auth",
+			`(?-i:[Aa]pi|API)`,
 			"credential",
 			"creds",
+			"key",
 			"passwd",
 			"password",
-			"auth",
-			"access",
-		}, `[0-9a-z\-_.=]{10,150}`, true),
+			"secret",
+			"token",
+		}, `[\w.=-]{10,150}`, true),
 		Keywords: []string{
-			"key",
+			"access",
 			"api",
-			"token",
-			"secret",
+			"auth",
+			"key",
 			"credential",
 			"creds",
 			"passwd",
 			"password",
-			"auth",
-			"access",
+			"secret",
+			"token",
 		},
 		Entropy: 3.5,
 		Allowlists: []config.Allowlist{
@@ -43,14 +43,27 @@ func GenericCredential() *config.Rule {
 				MatchCondition: config.AllowlistMatchOr,
 				Regexes: []*regexp.Regexp{
 					regexp.MustCompile(`(?i)(` +
-						`public[_.-]?(key|token)` + // public key -> not a secret
+						// Access
+						`accessor` +
+						// API
 						`|api[_.-]?(version|id)` + // version/id -> not a secret
-						`|(secret)[_.-]?name` + // name of e.g. env variable
+						`|rapid|capital` + // common words containing "api"
+						// Auth
+						`|author` +
+						// Credentials
+						`|(?-i:(?:c|jobC)redentials?Id|withCredentials)` + // Jenkins plugins
+						// Key
+						`|key[_.-]?(alias|board|code|ring|stone|storetype|word|up|down|left|right)` +
 						`|issuerkeyhash` + // part of ssl cert
+						`|(bucket|primary|foreign|natural|hot)[_.-]?key` +
 						`|(?-i:[DdMm]onkey|[DM]ONKEY)|keying` + // common words containing "key"
-						`|(primary|foreign|natural|definition|hot)[_.-]?key` +
-						`|key[_.-]?(alias|board|code|stone|storetype|word|up|down|left|right)` +
-						`|rapid|capital` + // common words containing "api"
+						// Secret
+						`|(secret)[_.-]?name` + // name of e.g. env variable
+						// Token
+
+						// General
+						`|public[_.-]?(key|token)` + // public key -> not a secret
+						`|(key|token)[_.-]?file` +
 						`)`),
 				},
 				RegexTarget: "match",
@@ -61,38 +74,83 @@ func GenericCredential() *config.Rule {
 
 	// validate
 	tps := []string{
-		utils.GenerateSampleSecret("generic", "CLOJARS_34bf0e88955ff5a1c328d6a7491acc4f48e865a7b8dd4d70a70749037443"), //gitleaks:allow
-		utils.GenerateSampleSecret("generic", "Zf3D0LXCM3EIMbgJpUNnkRtOfOueHznB"),
+		// Access
+		`'access_token': 'eyJ0eXAioiJKV1slS3oASx=='`,
+
+		// API
+		`some_api_token_123 = "` + newPlausibleSecret(`[a-zA-Z0-9]{60}`) + `"`,
+
+		// Auth
+		// Credentials
 		`"credentials" : "0afae57f3ccfd9d7f5767067bc48b30f719e271ba470488056e37ab35d4b6506"`,
-		`"client_secret" : "6da89121079f83b2eb6acccf8219ea982c3d79bccc3e9c6a85856480661f8fde",`,
-		`passwd = ` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+		`creds = ` + newPlausibleSecret(`[a-zA-Z0-9]{30}`),
+
+		// Key
 		`private-key: ` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{100}`),
+
+		// Password
+		`passwd = ` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+
+		// Secret
+		`"client_secret" : "6da89121079f83b2eb6acccf8219ea982c3d79bccc3e9c6a85856480661f8fde",`,
 		`mySecretString=` + newPlausibleSecret(`[a-zA-Z0-9]{30}`),
-		`some_api_token_123 = "` + newPlausibleSecret(`[a-zA-Z0-9]{60}`) + `"`,
 		`todo_secret_do_not_commit = ` + newPlausibleSecret(`[a-zA-Z0-9]{30}`),
-		`creds = ` + newPlausibleSecret(`[a-zA-Z0-9]{30}`),
+
+		// Token
+		utils.GenerateSampleSecret("generic", "CLOJARS_34bf0e88955ff5a1c328d6a7491acc4f48e865a7b8dd4d70a70749037443"), //gitleaks:allow
+		utils.GenerateSampleSecret("generic", "Zf3D0LXCM3EIMbgJpUNnkRtOfOueHznB"),
 	}
 	fps := []string{
-		`client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.client-vpn-endpoint.id`,
-		`password combination.
+		// Access
+		`"accessor":"rA1wk0Y45YCufyfq",`,
 
-R5: Regulatory--21`,
-		`public_key = "9Cnzj4p4WGeKLs1Pt8QuKUpRKfFLfRYC9AIKjbJTWit"`,
-		`publicToken = "9Cnzj4p4WGeKLs1Pt8QuKUpRKfFLfRYC9AIKjbJTWit"`,
-		`clientId = "73082700-1f09-405b-80d0-3131bfd6272d"`,
-		`MantleAPI_version=9a038989604e8da62ecddbe2094b16ce1b778be1`,
+		// API
+		`this.ultraPictureBox1.Name = "ultraPictureBox1";`,
+		`rapidstring:marm64-uwp=fail`,
+		`event-bus-message-api:rc0.15.0_20231217_1420-SNAPSHOT'`,
 		`COMMUNICATION_API_VERSION=rc0.13.0_20230412_0712-SNAPSHOT`,
-		`LLM_SECRET_NAME = "NEXUS-GPT4-API-KEY"`,
+		`MantleAPI_version=9a038989604e8da62ecddbe2094b16ce1b778be1`,
+
+		// Auth
+		`author = "james.fake@ymail.com",`,
+
+		// Credentials
+		`withCredentials([usernamePassword(credentialsId: '29f63271-dc2f-4734-8221-5b31b5169bac', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {`,
+		`credentialsId: 'ff083f76-7804-4ef1-80e4-fe975bb9141b'`,
+		`jobCredentialsId: 'f4aeb6bc-2a25-458a-8111-9be9e502c0e7'`,
+		`  "credentialId": "B9mTcFSck2LzJO2S3ols63",`,
+
+		// Key
 		`keyword: "Befaehigung_P2"`,
-		`minisat-master-keying:x64-uwp=fail`,
+		`public_key = "9Cnzj4p4WGeKLs1Pt8QuKUpRKfFLfRYC9AIKjbJTWit"`,
 		`monkeys-audio:mx64-uwp=fail`,
-		`rapidstring:marm64-uwp=fail`,
-		`<entry key="jetbrains.mps.v8_elimination" value="executed" />`,
-		`event-bus-message-api:rc0.15.0_20231217_1420-SNAPSHOT'`,
 		`primaryKey=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
 		`foreignKey=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
 		`key_down_event=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
 		`issuerKeyHash=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+		`<entry key="jetbrains.mps.v8_elimination" value="executed" />`,
+		`minisat-master-keying:x64-uwp=fail`,
+		`IceSSL.KeyFile=s_rsa1024_priv.pem`,
+		`"bucket_key": "SalesResults-1.2"`,
+		//`<TAR key="REF_ID_923.properties" value="/opts/config/alias/"/>`,
+		`<key tag="SecurityIdentifier" name="SecurityIdentifier" type="STRING" />`,
+		//`packageKey":` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+
+		// Password
+		`password combination.
+
+R5: Regulatory--21`,
+		`PuttyPassword=0`,
+
+		// Secret
+		`LLM_SECRET_NAME = "NEXUS-GPT4-API-KEY"`,
+
+		// Token
+		`publicToken = "9Cnzj4p4WGeKLs1Pt8QuKUpRKfFLfRYC9AIKjbJTWit"`,
+		`<SourceFile SourceLocation="F:\Extracts\" TokenFile="RTL_INST_CODE.cer">`,
+
+		// General
+		`clientId = "73082700-1f09-405b-80d0-3131bfd6272d"`,
 	}
 	return utils.Validate(r, tps, fps)
 }

+ 7 - 7
config/gitleaks.toml

@@ -532,25 +532,25 @@ keywords = ["aiza"]
 [[rules]]
 id = "generic-api-key"
 description = "Detected a Generic API Key, potentially exposing access to various services and sensitive operations."
-regex = '''(?i)[\w.-]{0,10}?(?:key|api|token|secret|credential|creds|passwd|password|auth|access)(?:[ \t\w.-]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9a-z\-_.=]{10,150})(?:['|\"|\n|\r|\s|\x60|;]|$)'''
+regex = '''(?i)[\w.-]{0,10}?(?:access|auth|(?-i:[Aa]pi|API)|credential|creds|key|passwd|password|secret|token)(?:[ \t\w.-]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([\w.=-]{10,150})(?:['|\"|\n|\r|\s|\x60|;]|$)'''
 entropy = 3.5
 keywords = [
-    "key",
+    "access",
     "api",
-    "token",
-    "secret",
+    "auth",
+    "key",
     "credential",
     "creds",
     "passwd",
     "password",
-    "auth",
-    "access",
+    "secret",
+    "token",
 ]
 # NOTE: Gitleaks >= v8.21.0 should use [[rules.allowlists] instead.
 [rules.allowlist]
 regexTarget = "match"
 regexes = [
-    '''(?i)(public[_.-]?(key|token)|api[_.-]?(version|id)|(secret)[_.-]?name|issuerkeyhash|(?-i:[DdMm]onkey|[DM]ONKEY)|keying|(primary|foreign|natural|definition|hot)[_.-]?key|key[_.-]?(alias|board|code|stone|storetype|word|up|down|left|right)|rapid|capital)''',
+    '''(?i)(accessor|api[_.-]?(version|id)|rapid|capital|author|(?-i:(?:c|jobC)redentials?Id|withCredentials)|key[_.-]?(alias|board|code|ring|stone|storetype|word|up|down|left|right)|issuerkeyhash|(bucket|primary|foreign|natural|hot)[_.-]?key|(?-i:[DdMm]onkey|[DM]ONKEY)|keying|(secret)[_.-]?name|public[_.-]?(key|token)|(key|token)[_.-]?file)''',
 ]
 stopwords = [
     "000000",