Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6e0c62d
Added check to ensure files of 'Kind' proto are ignored by 'Inspect',…
cx-andre-pereira Mar 25, 2026
99d42f6
Changed approach, proto files should flag if they have secrets within…
cx-andre-pereira Mar 26, 2026
bf11789
Fix expected results
cx-andre-pereira Mar 26, 2026
6f74701
Part 1 fix git diff
cx-andre-pereira Mar 26, 2026
ac15550
Part 2 fix git diff
cx-andre-pereira Mar 26, 2026
bb1c871
Fix regex rules (duplicated rule was removed but comma was missed)
cx-andre-pereira Mar 26, 2026
97cf527
Two more allow rules plus updated negative sample
cx-andre-pereira Mar 26, 2026
c13808d
Fallback, generic secret reqires 10 digits (impossible in proto) and …
cx-andre-pereira Mar 26, 2026
3b4a2c2
Removed unnecessar allow rule
cx-andre-pereira Mar 26, 2026
50fd363
Improved negative28 tests used for TF resource access allow rule in '…
cx-andre-pereira Mar 26, 2026
da78bfa
Minor test change
cx-andre-pereira Mar 27, 2026
d0de248
Expected results fix
cx-andre-pereira Mar 27, 2026
f1a09b5
Removed fixs unrelated to proto files fields (will be included in a s…
cx-andre-pereira Mar 27, 2026
03faf42
Merge branch 'master' of https://github.com/Checkmarx/kics into AST-1…
cx-andre-pereira Apr 10, 2026
54ad265
Initial approach to reduce False Positives on missing proto scenarios
cx-andre-pereira Apr 13, 2026
0678a20
Merge branch 'master' of https://github.com/Checkmarx/kics into AST-1…
cx-andre-pereira Apr 13, 2026
4146e92
Improved proto regex and added samples for new scenarios + generic se…
cx-andre-pereira Apr 14, 2026
525302c
Zero can be attributed (at the very least in enum messages), fixed re…
cx-andre-pereira Apr 14, 2026
8c2b691
Fix accidental change of encryption key id
cx-andre-pereira Apr 14, 2026
befc261
Fix expected results query names
cx-andre-pereira Apr 14, 2026
959a088
Minor improvements to regex to make them slightly more restrictive + …
cx-andre-pereira Apr 14, 2026
32aa132
New syntax possibility in sample to account for
cx-andre-pereira Apr 14, 2026
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
20 changes: 20 additions & 0 deletions assets/queries/common/passwords_and_secrets/regex_rules.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
{
"description": "Allow password retrieved from ARM parameters",
"regex": "(?i)['\"]?password['\"]?\\s*[:=]\\s*['\"]?\\s*,\\s*parameters\\(['\"]([a-zA-Z][a-zA-Z0-9_-]*)['\"]['\"]?\\)"
},
{
"description": "Avoiding Proto File fields",
"regex": "(?i)password\\s*=\\s*(0|[1-9][0-9]{0,8})\\s*(\\[.+=.+\\]\\s*;|\\[.+=.+,\\s*$|\\[\\s*$|;)"
}
],
"specialMask": "(?i)['\"]?password['\"]?\\s*[:=]\\s*"
Expand Down Expand Up @@ -83,6 +87,10 @@
{
"description": "Allow secrets retrieved from Bicep getSecret built in function",
"regex": "(?i)['\"]?secret[_]?(key|value)?['\"]?\\s*(:|=)\\s*[a-zA-Z]*\\.getSecret\\(\\s*[\"']([A-Za-z0-9/~^_!@#&%(){};=?*+-<>,:;[\\]%$]+)[\"']\\)"
},
{
"description": "Avoiding Proto File fields",
"regex": "(?i)secret[_]?(key|value)?\\s*=\\s*(0|[1-9][0-9]{0,8})\\s*(\\[.+=.+\\]\\s*;|\\[.+=.+,\\s*$|\\[\\s*$|;)"
}
],
"specialMask": "(?i)['\"]?secret[_]?(key)?['\"]?\\s*(:|=)\\s*"
Expand Down Expand Up @@ -279,6 +287,10 @@
{
"description": "Avoid Docker Compose secrets paths",
"regex": "(?i)['\"]?private[_]?key['\"]?\\s*[:=]\\s*['\"]?/run/secrets/\\w+['\"]?"
},
{
"description": "Avoiding Proto File fields",
"regex": "(?i)private[_]?key\\s*=\\s*(0|[1-9][0-9]{0,8})\\s*(\\[.+=.+\\]\\s*;|\\[.+=.+,\\s*$|\\[\\s*$|;)"
}
]
},
Expand Down Expand Up @@ -350,6 +362,10 @@
{
"description": "Avoiding Run After Triggers (if written in conformity with best practices)",
"regex": "(?i)['\"](HTTP|Parse_JSON|Try|Catch)_-_(Get_)?OAuth_Token['\"]?\\s*[:=]\\s*['\"]?([[A-Za-z0-9/~^_!@&%()=?*+-]+)['\"]?"
},
{
"description": "Avoiding Proto File fields",
"regex": "(?i)token(_)?(key)?\\s*=\\s*(0|[1-9][0-9]{0,8})\\s*(\\[.+=.+\\]\\s*;|\\[.+=.+,\\s*$|\\[\\s*$|;)"
}
],
"specialMask": "(?i)['\"]?token(_)?(key)?['\"]?\\s*[:=]\\s*"
Expand All @@ -373,6 +389,10 @@
{
"description": "Avoiding CLoudformation KeyName",
"regex": "['\"]?EncryptionKey['\"]?\\s*[:=]\\s*['\"]?([A-Za-z0-9/~^_!@&%()=?*+-.]+)['\"]?"
},
{
"description": "Avoiding Proto File fields",
"regex": "(?i)encryption[_]?key\\s*=\\s*(0|[1-9][0-9]{0,8})\\s*(\\[.+=.+\\]\\s*;|\\[.+=.+,\\s*$|\\[\\s*$|;)"
}
],
"specialMask": "(?i)['\"]?encryption[_]?key['\"]?\\s*[:=]\\s*"
Expand Down
141 changes: 141 additions & 0 deletions assets/queries/common/passwords_and_secrets/test/negative60.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// "Generic Token" - baee238e-1921-4801-9c3f-79ae1d7b2cbc - "Avoiding Proto File fields" allow-rule-test - #1
// "Generic Private Key" - 2f665079-c383-4b33-896e-88268c1fa258 - "Avoiding Proto File fields" allow rule test - #2
// "Encryption Key" - 9fb1cd65-7a07-4531-9bcf-47589d0f82d6 - "Avoiding Proto File fields" allow-rule-test - #3
// "Generic Password" - 487f4be7-3fd9-4506-a07a-eae252180c08 - "Avoiding Proto File fields" allow rule test - #4
// "Generic Secret" - 3e2d3b2f-c22a-4df1-9cc6-a7a0aebb0c99 - "Avoiding Proto File fields" allow rule test - #5
// Global allow rule - a88baa34-e2ad-44ea-ad6f-8cac87bc7c71 - "Avoiding Boolean's" allow-rule-test - #6
syntax = "proto3";
package com.example.security_test.v1;
import "google/protobuf/wrappers.proto";
option go_package = "github.com/CheckmarxDev/router-audit/gen/presets/v1;presets";

// Scenario 1 - Simple attribution
message SampleMessageNegative {
google.protobuf.StringValue refresh_token = 536870911; // if value is larger - out of range error "Field numbers cannot be greater than 536870911." - Generic Token #1
google.protobuf.StringValue sonar_token = 39;google.protobuf.StringValue codecov_token = 40;// trailing comment test - Generic Token #1

google.protobuf.StringValue access_token= 111111111; // Generic Token #1
google.protobuf.StringValue api_token = 7 ; // Generic Token #1
google.protobuf.StringValue token = 8; // Generic Token #1
google.protobuf.StringValue aws_session_token = 9; // Generic Token #1
google.protobuf.StringValue twilio_auth_token = 21; // Generic Token #1
google.protobuf.StringValue test_token_ = 122 ; // Generic Token #1

google.protobuf.StringValue jwt_private_key = 25; // Generic Private Key #2
google.protobuf.StringValue ssh_private_key = 26; // Generic Private Key #2
google.protobuf.StringValue tls_private_key = 27; // Generic Private Key #2
google.protobuf.StringValue ca_private_key = 28 ; // Generic Private Key #2
google.protobuf.StringValue private_key = 5; // Generic Private Key #2

google.protobuf.StringValue encryption_key = 22; // Encryption Key #3
google.protobuf.StringValue data_encryption_key= 23 ; // Encryption Key #3
google.protobuf.StringValue key_encryption_key=24; // Encryption Key #3

google.protobuf.StringValue registry_password = 10421; // Generic Password #4
google.protobuf.StringValue artifactory_password = 10731 ; // Generic Password #4
google.protobuf.StringValue nexus_password = 10853; // Generic Password #4
string password = 64114; // Generic Password #4

string secret_key = 123456789; // Generic Secret #5
string secret_value = 123456790; // Generic Secret #5
string secret = 123456791; // Generic Secret #5
}

// Scenario 2 - Attribution with options
message SampleMessageNegative2 {
google.protobuf.StringValue next_page_token = 5 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"test\""}]; // Generic Token #1
google.protobuf.StringValue next_next_page_token = 6[(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"test\""} ] ; // Generic Token #1
google.protobuf.StringValue api_token = 7 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"jira_api_token\""}]; // Generic Token #1

google.protobuf.StringValue next_page_private_key = 8 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"test\""}]; // Generic Private Key #2
google.protobuf.StringValue next_next_page_private_key = 8[(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"test\""} ] ; // Generic Private Key #2
google.protobuf.StringValue api_private_key = 10 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"jira_api_private_key\""}]; // Generic Private Key #2

google.protobuf.StringValue next_page_encryption_key = 11 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"test\""}]; // Encryption Key #3
google.protobuf.StringValue next_next_page_encryption_key = 12[(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"test\""} ] ; // Encryption Key #3
google.protobuf.StringValue api_encryption_key = 13 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"jira_api_encryption_key\""}]; // Encryption Key #3

google.protobuf.StringValue next_page_password = 14 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"test\""}]; // Generic Password #4
google.protobuf.StringValue next_next_page_password = 15[(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"test\""} ] ; // Generic Password #4
google.protobuf.StringValue api_password = 16 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"jira_api_password\""}]; // Generic Password #4

google.protobuf.StringValue next_page_secret = 17[(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"test\""}]; // Generic Secret #5
google.protobuf.StringValue next_next_page_secret = 18[(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"test\""} ] ; // Generic Secret #5
google.protobuf.StringValue api_secret = 19[(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"jira_api_secret\""}]; // Generic Secret #5
}

message MyOptions {
string file_only_option_token = 1 [targets = TARGET_TYPE_FILE]; // Generic Token #1
int message_and_enum_option_token = 2 [targets = TARGET_TYPE_MESSAGE,
targets = TARGET_TYPE_ENUM]; // Generic Token #1 (line above)

string file_only_option_private_key = 11 [targets = TARGET_TYPE_FILE]; // Generic Private Key #2
int message_and_enum_option_private_key = 21 [targets = TARGET_TYPE_MESSAGE,
targets = TARGET_TYPE_ENUM]; // Generic Private Key #2 (line above)

string file_only_option_encryption_key = 13 [targets = TARGET_TYPE_FILE]; // Encryption Key #3
int message_and_enum_option_encryption_key = 23 [targets = TARGET_TYPE_MESSAGE,
targets = TARGET_TYPE_ENUM]; // Encryption Key #3 (line above)

string file_only_option_password = 14 [targets = TARGET_TYPE_FILE]; // Generic Password #4
int message_and_enum_option_password = 24 [targets = TARGET_TYPE_MESSAGE,
targets = TARGET_TYPE_ENUM]; // Generic Password #4 (line above)

string file_only_option_secret = 15[targets = TARGET_TYPE_FILE]; // Generic Secret #5
int message_and_enum_option_secret = 25[targets = TARGET_TYPE_MESSAGE,
targets = TARGET_TYPE_ENUM]; // Generic Secret #5 (line above)

int B_message_and_enum_option_token = 2 [targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM]; // Generic Token #1

int B_message_and_enum_option_private_key = 211 [targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM]; // Generic Private Key #2

int B_message_and_enum_option_encryption_key = 232 [targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM]; // Encryption Key #3

int B_message_and_enum_option_password = 243 [targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM]; // Generic Password #4

int B_message_and_enum_option_secret = 254[targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM]; // Generic Secret #5
}

message Not_a_Token {
string token = 1 [json_name = "tk"]; // Generic Token #1
string private_key = 4 [json_name = "pk"]; // Generic Private Key #2
string encryption_key = 3 [json_name = "ek"]; // Encryption Key #3
string password = 2 [json_name = "ps"]; // Generic Password #4
string secret = 5[json_name = "se"]; // Generic Secret #5
}

// Scenario 3 - Enum attributions
enum Corpus {
DATA_A_UNSPECIFIED_TOKEN = 0 [ deprecated = true ] ; // Generic Token #1
DATA_A_TOKEN = 11[deprecated=true] ; // Generic Token #1 & #6
DATA_A_PRIVATE_KEY = 2[deprecated = false]; // Generic Private Key #2 & #6
DATA_A_ENCRYPTION_KEY = 3[deprecated = true]; // Encryption Key #3 & #6
DATA_A_PASSWORD = 1234 [deprecated = false]; // Generic Password #4 & #6
DATA_A_SECRET = 5[deprecated=true]; // Generic Secret #5 & #6

// Generic Token #1 (line below)
DATA_B_TOKEN = 2[
(string_name) = "display_value"
];
// Generic Private Key #2 (line below)
DATA_B_PRIVATE_KEY = 2 [
(string_name) = "display_value"
];
// Encryption Key #3 (line below)
DATA_B_ENCRYPTION_KEY = 2 [
(string_name) = "display_value"
];
// Generic Password #4 (line below)
DATA_B_PASSWORD = 28970[
(string_name) = "display_value"
];
// Generic Secret #5 (line below)
DATA_B_SECRET = 123456789[
(string_name) = "display_value"
];
}

// Scenario 4 - Generic keywords in "reserved"
enum EnumAllowingAlias {
reserved "password", "api_token", "private_key", "encryption_key", "exposed_secret";
option end_of_sample = false;}enum InlineMessageFormat{option end_of_sample = true;}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// "Generic Password" - 487f4be7-3fd9-4506-a07a-eae252180c08 - positive-test - #1
// "Generic Secret" - 3e2d3b2f-c22a-4df1-9cc6-a7a0aebb0c99 - positive-test - #2
// "Generic Token" - baee238e-1921-4801-9c3f-79ae1d7b2cbc - positive-test - #3
// "Generic Private Key" - 2f665079-c383-4b33-896e-88268c1fa258 - positive-test - #4
// "Encryption Key" - 9fb1cd65-7a07-4531-9bcf-47589d0f82d6 - positive-test - #5
// "Generic Password" - 487f4be7-3fd9-4506-a07a-eae252180c08 - "Avoiding Proto File fields" allow rule test - #6
// "Generic Token" - baee238e-1921-4801-9c3f-79ae1d7b2cbc - "Avoiding Proto File fields" allow-rule-test - #7
// "Encryption Key" - 9fb1cd65-7a07-4531-9bcf-47589d0f82d6 - "Avoiding Proto File fields" allow-rule-test - #8

syntax = "proto3";

// This sample should not flag the message defined only the exposed secrets in comments :
// "password" = "test_sample" #1
// "secret_key" : minimum_ten_characters #2
// "unsafe_token" : "is_this_safe" #3

package com.example.security_test.v1;

import "google/protobuf/wrappers.proto";

message InocentMessage {
google.protobuf.StringValue safe_value = 1;
double not_a_password = 22222; // #6
float not_a_token = 3; // #7
string not_an_encryption_key = 4; // #8
}


extend google.protobuf.FileOptions { // too generic for an allow rule
int32 source_retention_password = 12342134 //#1
[retention = RETENTION_SOURCE];
string source_retention_token = 12342135 //#3
[retention = RETENTION_SOURCE];
float source_retention_private_key = 12342137 //#4
[retention = RETENTION_SOURCE];
double source_retention_encryption_key = 12342136 //#5
[retention = RETENTION_SOURCE];
}
Original file line number Diff line number Diff line change
Expand Up @@ -460,5 +460,47 @@
"severity": "HIGH",
"line": 4,
"fileName": "positive55.json"
},
{
"queryName": "Passwords And Secrets - Generic Password",
"severity": "HIGH",
"line": 13,
"fileName": "positive56.proto"
},
{
"queryName": "Passwords And Secrets - Generic Secret",
"severity": "HIGH",
"line": 14,
"fileName": "positive56.proto"
},
{
"queryName": "Passwords And Secrets - Generic Token",
"severity": "HIGH",
"line": 15,
"fileName": "positive56.proto"
},
{
"queryName": "Passwords And Secrets - Generic Password",
"severity": "HIGH",
"line": 30,
"fileName": "positive56.proto"
},
{
"queryName": "Passwords And Secrets - Generic Token",
"severity": "HIGH",
"line": 32,
"fileName": "positive56.proto"
},
{
"queryName": "Passwords And Secrets - Generic Private Key",
"severity": "HIGH",
"line": 34,
"fileName": "positive56.proto"
},
{
"queryName": "Passwords And Secrets - Encryption Key",
"severity": "HIGH",
"line": 36,
"fileName": "positive56.proto"
}
]
43 changes: 43 additions & 0 deletions pkg/engine/secrets/inspector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,34 @@ var OriginalData7 = `# kics-scan disable=baee238e-1921-4801-9c3f-79ae1d7b2cbc
register: result
`

var OriginalData8 = `
syntax = "proto3";

package com.example.security_test.v1;

import "google/protobuf/wrappers.proto";

message ResultsThatFlag {
google.protobuf.StringValue refresh_token = 536870911; // if value is larger - out of range error "Field numbers cannot be greater than 536870911." - Generic Token
google.protobuf.StringValue access_token= 1; // Generic Token
google.protobuf.StringValue id_token = 3; // Generic Token
google.protobuf.StringValue bearer_toaken = 4;;; // Generic Token
google.protobuf.StringValue api_token = 7 ; // Generic Token
google.protobuf.StringValue token = 8; // Generic Token
google.protobuf.StringValue sonar_token = 39;google.protobuf.StringValue codecov_token = 40;// trailing comment test - Generic Token
google.protobuf.StringValue jwt_private_key = 25; // Generic Private Key
google.protobuf.StringValue ssh_private_key = 26; // Generic Private Key
google.protobuf.StringValue tls_private_key = 27; // Generic Private Key
google.protobuf.StringValue sp_private_key = 6; // Generic Private Key
google.protobuf.StringValue encryption_key = 22; // Encryption Key
google.protobuf.StringValue data_encryption_key= 23 ; // Encryption Key
google.protobuf.StringValue key_encryption_key=24; // Encryption Key
google.protobuf.StringValue registry_password = 104; // Generic Password
google.protobuf.StringValue artifactory_password = 107 ; // Generic Password
google.protobuf.StringValue nexus_password = 108; // Generic Password
string password = 64; // Generic Password
`

var testInspectInput = []struct {
name string
files model.FileMetadatas
Expand Down Expand Up @@ -418,6 +446,21 @@ var testInspectInput = []struct {
wantVuln: []model.Vulnerability{},
wantErr: false,
},
{
name: "valid_no_results",
files: model.FileMetadatas{
{
ID: "a6fbadc6-da29-4340-8d56-aa26a8852526",
Document: model.Document{},
OriginalData: OriginalData8,
LinesOriginalData: utils.SplitLines(OriginalData8),
Kind: "PROTO",
FilePath: "assets/queries/common/passwords_and_secrets/test/negative60.proto",
},
},
wantVuln: []model.Vulnerability{},
wantErr: false,
},
}

var testNewInspectorInputs = []struct {
Expand Down
Loading