diff --git a/detect_secrets/core/audit.py b/detect_secrets/core/audit.py index 00dda578a..9b373940d 100644 --- a/detect_secrets/core/audit.py +++ b/detect_secrets/core/audit.py @@ -152,6 +152,7 @@ def compare_baselines(old_baseline_filename, new_baseline_filename): total_reviews, plugins_used, additional_header_lines=header, + force=is_removed, ) decision = _get_user_decision( can_step_back=secret_iterator.can_step_back(), @@ -315,6 +316,7 @@ def _print_context( # pragma: no cover total, plugin_settings, additional_header_lines=None, + force=False, ): """ :type filename: str @@ -336,6 +338,10 @@ def _print_context( # pragma: no cover :param additional_header_lines: any additional lines to add to the header of the interactive audit display. + :type force: bool + :param force: if True, will print the lines of code even if it doesn't + find the secret expected + :raises: SecretNotFoundOnSpecifiedLineError """ print('{} {} {} {}\n{} {}\n{} {}'.format( @@ -359,6 +365,7 @@ def _print_context( # pragma: no cover filename, secret, plugin_settings, + force=force, ) print(secret_with_context) except SecretNotFoundOnSpecifiedLineError as e: @@ -421,6 +428,7 @@ def _get_secret_with_context( secret, plugin_settings, lines_of_context=5, + force=False, ): """ Displays the secret, with surrounding lines of code for better context. @@ -438,6 +446,10 @@ def _get_secret_with_context( :param lines_of_context: number of lines displayed before and after secret. + :type force: bool + :param force: if True, will print the lines of code even if it doesn't + find the secret expected + :raises: SecretNotFoundOnSpecifiedLineError """ secret_lineno = secret['line_number'] @@ -472,13 +484,24 @@ def _get_secret_with_context( # NOTE: index_of_secret_in_output should *always* be negative. index_of_secret_in_output = -trailing_lines_of_context - 1 - output[index_of_secret_in_output] = _highlight_secret( - output[index_of_secret_in_output], - secret_lineno, - secret, - filename, - plugin_settings, - ) + try: + output[index_of_secret_in_output] = _highlight_secret( + output[index_of_secret_in_output], + secret_lineno, + secret, + filename, + plugin_settings, + ) + except SecretNotFoundOnSpecifiedLineError: + if not force: + raise + + output[index_of_secret_in_output] = '{}'.format( + BashColor.color( + output[index_of_secret_in_output], + Color.BOLD, + ), + ) # Adding line numbers return '\n'.join( diff --git a/detect_secrets/plugins/basic_auth.py b/detect_secrets/plugins/basic_auth.py index eda4afb20..ff0b46e57 100644 --- a/detect_secrets/plugins/basic_auth.py +++ b/detect_secrets/plugins/basic_auth.py @@ -6,8 +6,12 @@ from detect_secrets.core.potential_secret import PotentialSecret +SPECIAL_URL_CHARACTERS = ':/?#[]@' BASIC_AUTH_REGEX = re.compile( - r'://[^:]+:([^@]+)@', + r'://[^{}\s]+:([^{}\s]+)@'.format( + re.escape(SPECIAL_URL_CHARACTERS), + re.escape(SPECIAL_URL_CHARACTERS), + ), ) diff --git a/tests/plugins/basic_auth_test.py b/tests/plugins/basic_auth_test.py index dbf3c4496..1477fcc75 100644 --- a/tests/plugins/basic_auth_test.py +++ b/tests/plugins/basic_auth_test.py @@ -11,6 +11,7 @@ class TestBasicAuthDetector(object): 'payload, should_flag', [ ('https://username:password@yelp.com', True,), + ('http://localhost:5000/<%= @variable %>', False,), ], ) def test_analyze_string(self, payload, should_flag):