From 434893b25cc6acd8565f82591beb205702bd8c61 Mon Sep 17 00:00:00 2001 From: Bernard A Boateng Date: Thu, 11 Apr 2019 10:23:27 -0400 Subject: [PATCH 1/6] More readable regex in keyword.py --- detect_secrets/plugins/keyword.py | 61 +++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/detect_secrets/plugins/keyword.py b/detect_secrets/plugins/keyword.py index 5c675bc48..16b99e395 100644 --- a/detect_secrets/plugins/keyword.py +++ b/detect_secrets/plugins/keyword.py @@ -118,46 +118,75 @@ 'true;', '{', } +QUOTE = r'[\'"]' +# includes ], ', " as closing +CLOSING = r'[]\'"]' +# non-greedy match +OPTIONAL_WHITESPACE = r'\s*?' +SECRET = r'[^\s]+' +BLACKLIST_REGEX = r'|'.join(BLACKLIST) + FOLLOWED_BY_COLON_REGEX = re.compile( # e.g. api_key: foo - r'({})(("|\')?):(\s*?)(("|\')?)([^\s]+)(\5)'.format( - r'|'.join(BLACKLIST), + r'({blacklist}){closing}?:{whitespace}({quote}?)({secret})(\2)'.format( + blacklist=BLACKLIST_REGEX, + closing=CLOSING, + quote=QUOTE, + whitespace=OPTIONAL_WHITESPACE, + secret=SECRET, ), ) FOLLOWED_BY_COLON_QUOTES_REQUIRED_REGEX = re.compile( # e.g. api_key: "foo" - r'({})(("|\')?):(\s*?)(("|\'))([^\s]+)(\5)'.format( - r'|'.join(BLACKLIST), + r'({blacklist}){closing}?:({whitespace})({quote})({secret})(\3)'.format( + blacklist=BLACKLIST_REGEX, + closing=CLOSING, + quote=QUOTE, + whitespace=OPTIONAL_WHITESPACE, + secret=SECRET, ), ) FOLLOWED_BY_EQUAL_SIGNS_REGEX = re.compile( # e.g. my_password = bar - r'({})((\'|")])?()(\s*?)=(\s*?)(("|\')?)([^\s]+)(\7)'.format( - r'|'.join(BLACKLIST), + r'({blacklist})({quote}?){closing}?{whitespace}={whitespace}({quote}?)({secret})(\3)'.format( + blacklist=BLACKLIST_REGEX, + closing=CLOSING, + quote=QUOTE, + whitespace=OPTIONAL_WHITESPACE, + secret=SECRET, ), ) FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_REGEX = re.compile( # e.g. my_password = "bar" - r'({})((\'|")])?()(\s*?)=(\s*?)(("|\'))([^\s]+)(\7)'.format( - r'|'.join(BLACKLIST), + r'({blacklist})({quote}?){closing}?{whitespace}={whitespace}({quote})({secret})(\3)'.format( + blacklist=BLACKLIST_REGEX, + closing=CLOSING, + quote=QUOTE, + whitespace=OPTIONAL_WHITESPACE, + secret=SECRET, ), ) FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX = re.compile( # e.g. private_key "something"; - r'({})([^\s]*?)(\s*?)("|\')([^\s]+)(\4);'.format( - r'|'.join(BLACKLIST), + r'({blacklist})({secret})?{whitespace}({quote})({secret})(\3);'.format( + blacklist=BLACKLIST_REGEX, + quote=QUOTE, + closing=CLOSING, + whitespace=OPTIONAL_WHITESPACE, + secret=SECRET, ), ) BLACKLIST_REGEX_TO_GROUP = { - FOLLOWED_BY_COLON_REGEX: 7, - FOLLOWED_BY_EQUAL_SIGNS_REGEX: 9, - FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 5, + FOLLOWED_BY_COLON_REGEX: 3, + FOLLOWED_BY_EQUAL_SIGNS_REGEX: 4, + FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 4, } QUOTES_REQUIRED_BLACKLIST_REGEX_TO_GROUP = { - FOLLOWED_BY_COLON_QUOTES_REQUIRED_REGEX: 7, - FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_REGEX: 9, - FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 5, + FOLLOWED_BY_COLON_QUOTES_REQUIRED_REGEX: 4, + FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_REGEX: 4, + FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 4, } + QUOTES_REQUIRED_FILETYPES = { FileType.CLS, FileType.JAVA, From b8aff5b84b0a211ae6b1dccd1b546827884cff31 Mon Sep 17 00:00:00 2001 From: Bernard A Boateng Date: Thu, 11 Apr 2019 11:03:59 -0400 Subject: [PATCH 2/6] split test strings into a dictionary --- tests/plugins/keyword_test.py | 179 ++++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 72 deletions(-) diff --git a/tests/plugins/keyword_test.py b/tests/plugins/keyword_test.py index af7d9511e..50c17d723 100644 --- a/tests/plugins/keyword_test.py +++ b/tests/plugins/keyword_test.py @@ -13,59 +13,108 @@ '.java', '.py', ) -STANDARD_NEGATIVES = [ - # FOLLOWED_BY_COLON_RE - 'theapikey: ""', # Nothing in the quotes - 'theapikey: "somefakekey"', # 'fake' in the secret - 'theapikeyforfoo:hopenobodyfindsthisone', # Characters between apikey and : - # FOLLOWED_BY_EQUAL_SIGNS_RE - 'some_key = "real_secret"', # We cannot make 'key' a Keyword, too noisy - 'my_password = foo(hey)you', # Has a ( followed by a ) - "my_password = request.json_body['hey']", # Has a [ followed by a ] - 'my_password = ""', # Nothing in the quotes - "my_password = ''", # Nothing in the quotes - 'my_password = True', # 'True' is a known false-positive - 'my_password = "fakesecret"', # 'fake' in the secret - 'login(username=username, password=password)', # secret is password) - 'open(self, password = ""):', # secrets is ""): - 'open(self, password = ""):', # secrets is ""): - # FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE - 'private_key "";', # Nothing in the quotes - 'private_key \'"no spaces\';', # Has whitespace in the secret - 'private_key "fake";', # 'fake' in the secret - 'private_key "hopenobodyfindsthisone\';', # Double-quote does not match single-quote - 'private_key \'hopenobodyfindsthisone";', # Single-quote does not match double-quote - 'password: ${link}', # Has a ${ followed by a } -] -STANDARD_POSITIVES = { - # FOLLOWED_BY_COLON_RE - "'theapikey': '{{h}o)p${e]nob(ody[finds>-_$#thisone}}'", - '"theapikey": "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"', - 'apikey: {{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'apikey:{{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'theapikey:{{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'apikey: "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"', - "apikey: '{{h}o)p${e]nob(ody[finds>-_$#thisone}}'", - # FOLLOWED_BY_EQUAL_SIGNS_RE - 'some_dict["secret"] = "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"', - "some_dict['secret'] = {{h}o)p${e]nob(ody[finds>-_$#thisone}}", - 'my_password={{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password= {{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password ={{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password = {{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password ={{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'the_password={{h}o)p${e]nob(ody[finds>-_$#thisone}}\n', - 'the_password= "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"\n', - 'the_password=\'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\'\n', - # FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE - 'apikey "{{h}o)p${e]nob(ody[finds>-_$#thisone}}";', # Double-quotes - 'fooapikeyfoo "{{h}o)p${e]nob(ody[finds>-_$#thisone}}";', # Double-quotes - 'fooapikeyfoo"{{h}o)p${e]nob(ody[finds>-_$#thisone}}";', # Double-quotes - 'private_key \'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\';', # Single-quotes - 'fooprivate_keyfoo\'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\';', # Single-quotes - 'fooprivate_key\'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\';', # Single-quotes +FOLLOWED_BY_COLON_RE = { + "negatives": { + "quotes_required": [ + 'theapikey: ""', # Nothing in the quotes + 'theapikey: "somefakekey"', # 'fake' in the secret + ], + "quotes_not_required": [ + 'theapikeyforfoo:hopenobodyfindsthisone', # Characters between apikey and : + ], + }, + "positives": { + "quotes_required": [ + "'theapikey': '{{h}o)p${e]nob(ody[finds>-_$#thisone}}'", + '"theapikey": "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"', + 'apikey: "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"', + "apikey: '{{h}o)p${e]nob(ody[finds>-_$#thisone}}'", + ], + "quotes_not_required": [ + 'apikey: {{h}o)p${e]nob(ody[finds>-_$#thisone}}', + 'apikey:{{h}o)p${e]nob(ody[finds>-_$#thisone}}', + 'theapikey:{{h}o)p${e]nob(ody[finds>-_$#thisone}}', + ], + }, +} +FOLLOWED_BY_EQUAL_SIGNS_RE = { + "negatives": { + "quotes_required": [ + 'some_key = "real_secret"', # We cannot make 'key' a Keyword, too noisy + 'my_password = ""', # Nothing in the quotes + "my_password = ''", # Nothing in the quotes + 'my_password = "fakesecret"', # 'fake' in the secret + 'open(self, password = ""):', # secrets is ""): + 'open(self, password = ""):', # secrets is ""): + ], + "quotes_not_required": [ + 'my_password = foo(hey)you', # Has a ( followed by a ) + "my_password = request.json_body['hey']", # Has a [ followed by a ] + 'my_password = True', # 'True' is a known false-positive + 'login(username=username, password=password)', # secret is password) + ], + }, + "positives": { + "quotes_required": [ + 'some_dict["secret"] = "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"', + 'the_password= "{{h}o)p${e]nob(ody[finds>-_$#thisone}}"\n', + 'the_password=\'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\'\n', + ], + "quotes_not_required": [ + "some_dict['secret'] = {{h}o)p${e]nob(ody[finds>-_$#thisone}}", + 'my_password={{h}o)p${e]nob(ody[finds>-_$#thisone}}', + 'my_password= {{h}o)p${e]nob(ody[finds>-_$#thisone}}', + 'my_password ={{h}o)p${e]nob(ody[finds>-_$#thisone}}', + 'my_password = {{h}o)p${e]nob(ody[finds>-_$#thisone}}', + 'my_password ={{h}o)p${e]nob(ody[finds>-_$#thisone}}', + 'the_password={{h}o)p${e]nob(ody[finds>-_$#thisone}}\n', + ], + }, +} +FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE = { + "negatives": { + "quotes_required": [ + 'private_key "";', # Nothing in the quotes + 'private_key \'"no spaces\';', # Has whitespace in the secret + 'private_key "fake";', # 'fake' in the secret + 'private_key "hopenobodyfindsthisone\';', # Double-quote does not match single-quote + 'private_key \'hopenobodyfindsthisone";', # Single-quote does not match double-quote + ], + "quotes_not_required": [ + 'password: ${link}', # Has a ${ followed by a } + ], + }, + "positives": { + "quotes_required": [ + 'apikey "{{h}o)p${e]nob(ody[finds>-_$#thisone}}";', # Double-quotes + 'fooapikeyfoo "{{h}o)p${e]nob(ody[finds>-_$#thisone}}";', # Double-quotes + 'fooapikeyfoo"{{h}o)p${e]nob(ody[finds>-_$#thisone}}";', # Double-quotes + 'private_key \'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\';', # Single-quotes + 'fooprivate_keyfoo\'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\';', # Single-quotes + 'fooprivate_key\'{{h}o)p${e]nob(ody[finds>-_$#thisone}}\';', # Single-quotes + ], + }, } +STANDARD_NEGATIVES = [] +STANDARD_POSITIVES = [] + +STANDARD_NEGATIVES.extend( + FOLLOWED_BY_COLON_RE.get("negatives").get("quotes_required") + + FOLLOWED_BY_COLON_RE.get("negatives").get("quotes_not_required") + + FOLLOWED_BY_EQUAL_SIGNS_RE.get("negatives").get("quotes_required") + + FOLLOWED_BY_EQUAL_SIGNS_RE.get("negatives").get("quotes_not_required") + + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("negatives").get("quotes_required") + + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("negatives").get("quotes_not_required") +) +STANDARD_POSITIVES.extend( + FOLLOWED_BY_COLON_RE.get("positives").get("quotes_required") + + FOLLOWED_BY_COLON_RE.get("positives").get("quotes_not_required") + + FOLLOWED_BY_EQUAL_SIGNS_RE.get("positives").get("quotes_required") + + FOLLOWED_BY_EQUAL_SIGNS_RE.get("positives").get("quotes_not_required") + + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("positives").get("quotes_required"), +) + class TestKeywordDetector(object): @@ -82,8 +131,8 @@ def test_analyze_standard_positives(self, file_content): for potential_secret in output: assert 'mock_filename' == potential_secret.filename assert ( - potential_secret.secret_hash == - PotentialSecret.hash_secret('{{h}o)p${e]nob(ody[finds>-_$#thisone}}') + potential_secret.secret_hash + == PotentialSecret.hash_secret('{{h}o)p${e]nob(ody[finds>-_$#thisone}}') ) @pytest.mark.parametrize( @@ -102,20 +151,9 @@ def test_analyze_with_line_exclude(self, file_content): ( (positive, file_extension) for positive in ( - STANDARD_POSITIVES - { - # FOLLOWED_BY_COLON_QUOTES_REQUIRED_RE - 'apikey: {{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'apikey:{{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'theapikey:{{h}o)p${e]nob(ody[finds>-_$#thisone}}', - # FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_RE - "some_dict['secret'] = {{h}o)p${e]nob(ody[finds>-_$#thisone}}", - 'my_password={{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password= {{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password ={{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password = {{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'my_password ={{h}o)p${e]nob(ody[finds>-_$#thisone}}', - 'the_password={{h}o)p${e]nob(ody[finds>-_$#thisone}}\n', - } + FOLLOWED_BY_COLON_RE.get("positives").get("quotes_required") + + FOLLOWED_BY_EQUAL_SIGNS_RE.get("positives").get("quotes_required") + + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("positives").get("quotes_required") ) for file_extension in QUOTES_REQUIRED_FILE_EXTENSIONS ), ) @@ -129,8 +167,8 @@ def test_analyze_quotes_required_positives(self, file_content, file_extension): for potential_secret in output: assert mock_filename == potential_secret.filename assert ( - potential_secret.secret_hash == - PotentialSecret.hash_secret('{{h}o)p${e]nob(ody[finds>-_$#thisone}}') + potential_secret.secret_hash + == PotentialSecret.hash_secret('{{h}o)p${e]nob(ody[finds>-_$#thisone}}') ) @pytest.mark.parametrize( @@ -180,9 +218,6 @@ def test_analyze_php_negatives(self, file_content): for negative in ( STANDARD_NEGATIVES + [ # FOLLOWED_BY_COLON_QUOTES_REQUIRED_RE - 'apikey: hope]nobody[finds>-_$#thisone', - 'apikey:hope]nobody[finds>-_$#thisone', - 'theapikey:hope]nobody[finds>-_$#thisone', # FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_RE "some_dict['secret'] = hope]nobody[finds>-_$#thisone", 'my_password=hope]nobody[finds>-_$#thisone', From 16e8825ac68410f61a30839f47b97820dc5d7354 Mon Sep 17 00:00:00 2001 From: Bernard A Boateng Date: Thu, 11 Apr 2019 11:07:57 -0400 Subject: [PATCH 3/6] rollback --- detect_secrets/plugins/keyword.py | 63 +++++++++---------------------- 1 file changed, 17 insertions(+), 46 deletions(-) diff --git a/detect_secrets/plugins/keyword.py b/detect_secrets/plugins/keyword.py index 16b99e395..0008a166e 100644 --- a/detect_secrets/plugins/keyword.py +++ b/detect_secrets/plugins/keyword.py @@ -118,75 +118,46 @@ 'true;', '{', } -QUOTE = r'[\'"]' -# includes ], ', " as closing -CLOSING = r'[]\'"]' -# non-greedy match -OPTIONAL_WHITESPACE = r'\s*?' -SECRET = r'[^\s]+' -BLACKLIST_REGEX = r'|'.join(BLACKLIST) - FOLLOWED_BY_COLON_REGEX = re.compile( # e.g. api_key: foo - r'({blacklist}){closing}?:{whitespace}({quote}?)({secret})(\2)'.format( - blacklist=BLACKLIST_REGEX, - closing=CLOSING, - quote=QUOTE, - whitespace=OPTIONAL_WHITESPACE, - secret=SECRET, + r'({})(("|\')?):(\s*?)(("|\')?)([^\s]+)(\5)'.format( + r'|'.join(BLACKLIST), ), ) FOLLOWED_BY_COLON_QUOTES_REQUIRED_REGEX = re.compile( # e.g. api_key: "foo" - r'({blacklist}){closing}?:({whitespace})({quote})({secret})(\3)'.format( - blacklist=BLACKLIST_REGEX, - closing=CLOSING, - quote=QUOTE, - whitespace=OPTIONAL_WHITESPACE, - secret=SECRET, + r'({})(("|\')?):(\s*?)(("|\'))([^\s]+)(\5)'.format( + r'|'.join(BLACKLIST), ), ) FOLLOWED_BY_EQUAL_SIGNS_REGEX = re.compile( # e.g. my_password = bar - r'({blacklist})({quote}?){closing}?{whitespace}={whitespace}({quote}?)({secret})(\3)'.format( - blacklist=BLACKLIST_REGEX, - closing=CLOSING, - quote=QUOTE, - whitespace=OPTIONAL_WHITESPACE, - secret=SECRET, + r'({})((\'|")])?()(\s*?)=(\s*?)(("|\')?)([^\s]+)(\7)'.format( + r'|'.join(BLACKLIST), ), ) FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_REGEX = re.compile( # e.g. my_password = "bar" - r'({blacklist})({quote}?){closing}?{whitespace}={whitespace}({quote})({secret})(\3)'.format( - blacklist=BLACKLIST_REGEX, - closing=CLOSING, - quote=QUOTE, - whitespace=OPTIONAL_WHITESPACE, - secret=SECRET, + r'({})((\'|")])?()(\s*?)=(\s*?)(("|\'))([^\s]+)(\7)'.format( + r'|'.join(BLACKLIST), ), ) FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX = re.compile( # e.g. private_key "something"; - r'({blacklist})({secret})?{whitespace}({quote})({secret})(\3);'.format( - blacklist=BLACKLIST_REGEX, - quote=QUOTE, - closing=CLOSING, - whitespace=OPTIONAL_WHITESPACE, - secret=SECRET, + r'({})([^\s]*?)(\s*?)("|\')([^\s]+)(\4);'.format( + r'|'.join(BLACKLIST), ), ) BLACKLIST_REGEX_TO_GROUP = { - FOLLOWED_BY_COLON_REGEX: 3, - FOLLOWED_BY_EQUAL_SIGNS_REGEX: 4, - FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 4, + FOLLOWED_BY_COLON_REGEX: 7, + FOLLOWED_BY_EQUAL_SIGNS_REGEX: 9, + FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 5, } QUOTES_REQUIRED_BLACKLIST_REGEX_TO_GROUP = { - FOLLOWED_BY_COLON_QUOTES_REQUIRED_REGEX: 4, - FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_REGEX: 4, - FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 4, + FOLLOWED_BY_COLON_QUOTES_REQUIRED_REGEX: 7, + FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_REGEX: 9, + FOLLOWED_BY_QUOTES_AND_SEMICOLON_REGEX: 5, } - QUOTES_REQUIRED_FILETYPES = { FileType.CLS, FileType.JAVA, @@ -306,4 +277,4 @@ def probably_false_positive(lowered_secret, filetype): except ValueError: pass - return False + return False \ No newline at end of file From 6fd0aa4c650ba0e80df7091909f1e4e46fd143f1 Mon Sep 17 00:00:00 2001 From: Bernard A Boateng Date: Thu, 11 Apr 2019 11:15:01 -0400 Subject: [PATCH 4/6] add test case back --- tests/plugins/keyword_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/plugins/keyword_test.py b/tests/plugins/keyword_test.py index 50c17d723..8ee8fb0b4 100644 --- a/tests/plugins/keyword_test.py +++ b/tests/plugins/keyword_test.py @@ -218,6 +218,9 @@ def test_analyze_php_negatives(self, file_content): for negative in ( STANDARD_NEGATIVES + [ # FOLLOWED_BY_COLON_QUOTES_REQUIRED_RE + 'apikey: hope]nobody[finds>-_$#thisone', + 'apikey:hope]nobody[finds>-_$#thisone', + 'theapikey:hope]nobody[finds>-_$#thisone', # FOLLOWED_BY_EQUAL_SIGNS_QUOTES_REQUIRED_RE "some_dict['secret'] = hope]nobody[finds>-_$#thisone", 'my_password=hope]nobody[finds>-_$#thisone', From d78b954782547eb870f60c702a0e34b88ed28bf1 Mon Sep 17 00:00:00 2001 From: Bernard A Boateng Date: Thu, 11 Apr 2019 11:35:42 -0400 Subject: [PATCH 5/6] minor change --- tests/plugins/keyword_test.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/plugins/keyword_test.py b/tests/plugins/keyword_test.py index 8ee8fb0b4..2ec1b7123 100644 --- a/tests/plugins/keyword_test.py +++ b/tests/plugins/keyword_test.py @@ -21,6 +21,7 @@ ], "quotes_not_required": [ 'theapikeyforfoo:hopenobodyfindsthisone', # Characters between apikey and : + 'password: ${link}', # Has a ${ followed by a } ], }, "positives": { @@ -80,9 +81,6 @@ 'private_key "hopenobodyfindsthisone\';', # Double-quote does not match single-quote 'private_key \'hopenobodyfindsthisone";', # Single-quote does not match double-quote ], - "quotes_not_required": [ - 'password: ${link}', # Has a ${ followed by a } - ], }, "positives": { "quotes_required": [ @@ -105,7 +103,6 @@ + FOLLOWED_BY_EQUAL_SIGNS_RE.get("negatives").get("quotes_required") + FOLLOWED_BY_EQUAL_SIGNS_RE.get("negatives").get("quotes_not_required") + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("negatives").get("quotes_required") - + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("negatives").get("quotes_not_required") ) STANDARD_POSITIVES.extend( FOLLOWED_BY_COLON_RE.get("positives").get("quotes_required") From b95a97401d10e9c077e4589a15a68889b9ecd9c5 Mon Sep 17 00:00:00 2001 From: Bernard A Boateng Date: Thu, 11 Apr 2019 12:10:13 -0400 Subject: [PATCH 6/6] fix build failures --- detect_secrets/plugins/keyword.py | 2 +- tests/plugins/keyword_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/detect_secrets/plugins/keyword.py b/detect_secrets/plugins/keyword.py index 0008a166e..5c675bc48 100644 --- a/detect_secrets/plugins/keyword.py +++ b/detect_secrets/plugins/keyword.py @@ -277,4 +277,4 @@ def probably_false_positive(lowered_secret, filetype): except ValueError: pass - return False \ No newline at end of file + return False diff --git a/tests/plugins/keyword_test.py b/tests/plugins/keyword_test.py index 2ec1b7123..a686f4787 100644 --- a/tests/plugins/keyword_test.py +++ b/tests/plugins/keyword_test.py @@ -102,7 +102,7 @@ + FOLLOWED_BY_COLON_RE.get("negatives").get("quotes_not_required") + FOLLOWED_BY_EQUAL_SIGNS_RE.get("negatives").get("quotes_required") + FOLLOWED_BY_EQUAL_SIGNS_RE.get("negatives").get("quotes_not_required") - + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("negatives").get("quotes_required") + + FOLLOWED_BY_QUOTES_AND_SEMICOLON_RE.get("negatives").get("quotes_required"), ) STANDARD_POSITIVES.extend( FOLLOWED_BY_COLON_RE.get("positives").get("quotes_required")