Skip to content
Open
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
2 changes: 1 addition & 1 deletion detect_secrets/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = '0.13.1+ibm.62.dss'
VERSION = '0.13.1+ibm.63.dss'
5 changes: 5 additions & 0 deletions detect_secrets/core/baseline.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
def initialize(
path,
plugins,
plugins_reuse_exclude=None,
exclude_files_regex=None,
exclude_lines_regex=None,
word_list_file=None,
Expand All @@ -33,6 +34,9 @@ def initialize(
:type plugins: tuple of detect_secrets.plugins.base.BasePlugin
:param plugins: rules to initialize the SecretsCollection with.

:type plugins_reuse_exclude: bool|None
:param plugins_reuse_exclude optional bool indicating whether plugins were forced to reuse excludes.

:type exclude_files_regex: str|None
:type exclude_lines_regex: str|None

Expand All @@ -53,6 +57,7 @@ def initialize(
"""
output = SecretsCollection(
plugins,
plugins_reuse_exclude=plugins_reuse_exclude,
exclude_files=exclude_files_regex,
exclude_lines=exclude_lines_regex,
word_list_file=word_list_file,
Expand Down
3 changes: 3 additions & 0 deletions detect_secrets/core/secrets_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class SecretsCollection:
def __init__(
self,
plugins=(),
plugins_reuse_exclude=None,
exclude_files=None,
exclude_lines=None,
word_list_file=None,
Expand All @@ -46,6 +47,7 @@ def __init__(
"""
self.data = {}
self.plugins = plugins
self.plugins_reuse_exclude = plugins_reuse_exclude
self.exclude_files = exclude_files
self.exclude_lines = exclude_lines
self.word_list_file = word_list_file
Expand Down Expand Up @@ -342,6 +344,7 @@ def format_for_baseline_output(self):
plugins_used = sorted(plugins_used, key=lambda x: x['name'])

return {
**({"plugins_reuse_excludes": True} if self.plugins_reuse_exclude else {}),
'generated_at': strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()),
'exclude': {
'files': self.exclude_files,
Expand Down
17 changes: 17 additions & 0 deletions detect_secrets/core/usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
from detect_secrets.constants import DEFAULT_GHE_INSTANCE


def add_plugins_reuse_exclude_flag(parser):
parser.add_argument(
'--plugins-reuse-excludes',
action='store_true',
help='Force plugins to try re-using existing exclude contents.'
)


def add_exclude_lines_argument(parser):
parser.add_argument(
'--exclude-lines',
Expand Down Expand Up @@ -89,6 +97,7 @@ def add_default_arguments(self):

def add_pre_commit_arguments(self):
self._add_filenames_argument()\
._add_plugins_reuse_exclude_flag()\
._add_set_baseline_argument()\
._add_exclude_lines_argument()\
._add_word_list_argument()\
Expand Down Expand Up @@ -154,6 +163,10 @@ def _add_set_baseline_argument(self):
)
return self

def _add_plugins_reuse_exclude_flag(self):
add_plugins_reuse_exclude_flag(self.parser)
return self

def _add_exclude_lines_argument(self):
add_exclude_lines_argument(self.parser)
return self
Expand Down Expand Up @@ -222,6 +235,10 @@ def _add_initialize_baseline_argument(self):
),
)

# Pairing `--plugins-reuse-excludes` to
# both pre-commit and `--scan` because it can be used for both.
add_plugins_reuse_exclude_flag(self.parser)

# Pairing `--exclude-lines` and `--word-list` to
# both pre-commit and `--scan` because it can be used for both.
add_exclude_lines_argument(self.parser)
Expand Down
21 changes: 21 additions & 0 deletions detect_secrets/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ def parse_args(argv, parserBuilder):
return parserBuilder.add_console_use_arguments().parse_args(argv)


def maybe_get_existing_exclude(exclude_files, exclude_lines, old_baseline):
if not old_baseline:
return exclude_files, exclude_lines

previously_included = old_baseline.get("exclude", None)
if not previously_included:
return exclude_files, exclude_lines

files = "|".join(filter(None, (exclude_files, previously_included.get("files",None))))
lines = "|".join(filter(None, (exclude_lines, previously_included.get("lines",None))))

return files, lines

def main(argv=None):
if len(sys.argv) == 1: # pragma: no cover
sys.argv.append('-h')
Expand All @@ -36,6 +49,10 @@ def main(argv=None):
if args.word_list_file:
automaton, word_list_hash = build_automaton(args.word_list_file)

_baseline = _get_existing_baseline(args.import_filename)
if args.plugins_reuse_excludes or (_baseline and _baseline.get("plugins_reuse_excludes", False)):
args.exclude_files, args.exclude_lines = maybe_get_existing_exclude(args.exclude_files, args.exclude_lines, _baseline)

# Plugins are *always* rescanned with fresh settings, because
# we want to get the latest updates.
plugins = initialize.from_parser_builder(
Expand Down Expand Up @@ -173,13 +190,17 @@ def _perform_scan(args, plugins, automaton, word_list_hash):
if not args.word_list_file and old_baseline.get('word_list'):
args.word_list_file = old_baseline['word_list']['file']

if not args.plugins_reuse_excludes:
args.plugins_reuse_excludes = old_baseline.get('plugins_reuse_excludes', False)

# If we have knowledge of an existing baseline file, we should use
# that knowledge and add it to our exclude_files regex.
if args.import_filename:
_add_baseline_to_exclude_files(args)

new_baseline = baseline.initialize(
plugins=plugins,
plugins_reuse_exclude=args.plugins_reuse_excludes,
exclude_files_regex=args.exclude_files,
exclude_lines_regex=args.exclude_lines,
word_list_file=args.word_list_file,
Expand Down
5 changes: 5 additions & 0 deletions tests/main_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def test_scan_basic(self, mock_baseline_initialize):

mock_baseline_initialize.assert_called_once_with(
plugins=Any(tuple),
plugins_reuse_excludes=None,
exclude_files_regex=None,
exclude_lines_regex=None,
path='.',
Expand All @@ -104,6 +105,7 @@ def test_scan_with_rootdir(self, mock_baseline_initialize):

mock_baseline_initialize.assert_called_once_with(
plugins=Any(tuple),
plugins_reuse_excludes=None,
exclude_files_regex=None,
exclude_lines_regex=None,
path=['test_data'],
Expand All @@ -123,6 +125,7 @@ def test_scan_with_exclude_args(self, mock_baseline_initialize):

mock_baseline_initialize.assert_called_once_with(
plugins=Any(tuple),
plugins_reuse_excludes=None,
exclude_files_regex='some_pattern_here',
exclude_lines_regex='other_patt',
path='.',
Expand Down Expand Up @@ -208,6 +211,7 @@ def test_scan_with_all_files_flag(self, mock_baseline_initialize):

mock_baseline_initialize.assert_called_once_with(
plugins=Any(tuple),
plugins_reuse_excludes=None,
exclude_files_regex=None,
exclude_lines_regex=None,
path='.',
Expand Down Expand Up @@ -265,6 +269,7 @@ def test_reads_non_existed_baseline_from_file(

mock_baseline_initialize.assert_called_once_with(
plugins=Any(tuple),
plugins_reuse_excludes=None,
exclude_files_regex='^non_existed_baseline_file$',
exclude_lines_regex=None,
path='.',
Expand Down