예제 #1
0
 def test_fails_on_bad_initialization(self):
     with mock.patch.object(
             HexHighEntropyString,
             '__init__',
             side_effect=TypeError,
     ), pytest.raises(TypeError, ):
         initialize.from_plugin_classname(
             'HexHighEntropyString',
             hex_limit=4,
         )
예제 #2
0
 def test_fails_on_bad_initialization(self):
     with mock.patch(
         'detect_secrets.plugins.common.initialize.import_plugins',
         # Trying to instantiate str() like a plugin throws TypeError
         return_value={'HexHighEntropyString': str},
     ), pytest.raises(
         TypeError,
     ):
         initialize.from_plugin_classname(
             plugin_classname='HexHighEntropyString',
             custom_plugin_paths=(),
             hex_limit=4,
         )
예제 #3
0
    def test_success(self):
        plugin = initialize.from_plugin_classname(
            'HexHighEntropyString',
            hex_limit=4,
        )

        assert isinstance(plugin, HexHighEntropyString)
        assert plugin.entropy_limit == 4
예제 #4
0
    def load_baseline_from_dict(cls, data):
        """Initializes a SecretsCollection object from dictionary.

        :type data: dict
        :param data: properly formatted dictionary to load SecretsCollection from.

        :rtype: SecretsCollection
        :raises: IOError
        """
        result = SecretsCollection()

        if not all(key in data for key in (
                'plugins_used',
                'results',
        )):
            raise IOError

        # In v0.12.0 `exclude_regex` got replaced by `exclude`
        if not any(key in data for key in (
                'exclude',
                'exclude_regex',
        )):
            raise IOError

        if 'exclude_regex' in data:
            result.exclude_files = data['exclude_regex']
        else:
            result.exclude_files = data['exclude']['files']
            result.exclude_lines = data['exclude']['lines']

        plugins = []
        for plugin in data['plugins_used']:
            plugin_classname = plugin.pop('name')
            plugins.append(
                initialize.from_plugin_classname(
                    plugin_classname,
                    exclude_lines_regex=result.exclude_lines,
                    should_verify_secrets=False,
                    **plugin), )
        result.plugins = tuple(plugins)

        for filename in data['results']:
            result.data[filename] = {}

            for item in data['results'][filename]:
                secret = PotentialSecret(
                    item['type'],
                    filename,
                    secret='will be replaced',
                    lineno=item['line_number'],
                    is_secret=item.get('is_secret'),
                )
                secret.secret_hash = item['hashed_secret']
                result.data[filename][secret] = secret

        result.version = (data['version'] if 'version' in data else '0.0.0')

        return result
예제 #5
0
    def test_success(self):
        plugin = initialize.from_plugin_classname(
            plugin_classname='HexHighEntropyString',
            custom_plugin_paths=(),
            hex_limit=4,
        )

        # Dynamically imported classes have different
        # addresses for the same functions as statically
        # imported classes do, so isinstance does not work.
        assert str(plugin.__class__) == str(HexHighEntropyString)
        assert dir(plugin.__class__) == dir(HexHighEntropyString)

        assert plugin.entropy_limit == 4
예제 #6
0
    def load_baseline_from_dict(cls, data, plugin_filenames=None):
        """Initializes a SecretsCollection object from dictionary.

        :type data: dict
        :param data: properly formatted dictionary to load SecretsCollection from.

        :type plugin_filenames: tuple
        :param plugin_filenames: the plugin filenames.

        :rtype: SecretsCollection
        :raises: IOError
        """
        result = SecretsCollection()

        if not all(key in data for key in (
                'plugins_used',
                'results',
        )):
            raise IOError

        # In v0.12.0 `exclude_regex` got replaced by `exclude`
        if not any(key in data for key in (
                'exclude',
                'exclude_regex',
        )):
            raise IOError

        if 'exclude_regex' in data:
            result.exclude_files = data['exclude_regex']
        else:
            result.exclude_files = data['exclude']['files']
            result.exclude_lines = data['exclude']['lines']

        # In v0.12.7 the `--word-list` option got added
        automaton = None
        if 'word_list' in data:
            result.word_list_file = data['word_list']['file']
            result.word_list_hash = data['word_list']['hash']

            if result.word_list_file:
                # Always ignore the given `data['word_list']['hash']`
                # The difference will show whenever the word list changes
                automaton, result.word_list_hash = build_automaton(
                    result.word_list_file)

        plugins = []
        for plugin in data['plugins_used']:
            plugin_classname = plugin.pop('name')
            initialized_plugin_classname = initialize.from_plugin_classname(
                plugin_classname,
                exclude_lines_regex=result.exclude_lines,
                automaton=automaton,
                should_verify_secrets=True,
                plugin_filenames=plugin_filenames,
                **plugin,
            )
            if initialized_plugin_classname is not None:
                plugins.append(initialized_plugin_classname)
        result.plugins = tuple(plugins)

        for filename in data['results']:
            result.data[filename] = {}

            for item in data['results'][filename]:
                secret = PotentialSecret(
                    item['type'],
                    filename,
                    secret='will be replaced',
                    lineno=item['line_number'],
                    is_secret=item.get('is_secret'),
                    output_raw=result.output_raw,
                    is_verified=item['is_verified'],
                    verified_result=item.get('verified_result'),
                )
                secret.secret_hash = item['hashed_secret']
                result.data[filename][secret] = secret

        result.version = (data['version'] if 'version' in data else '0.0.0')

        return result
예제 #7
0
    def load_baseline_from_dict(cls, data):
        """Initializes a SecretsCollection object from dictionary.

        :type data: dict
        :param data: properly formatted dictionary to load SecretsCollection from.

        :rtype: SecretsCollection
        :raises: IOError
        """
        result = SecretsCollection()

        if not all(key in data for key in (
                'plugins_used',
                'results',
        )):
            raise IOError

        # In v0.12.0 `exclude_regex` got replaced by `exclude`
        if not any(key in data for key in (
                'exclude',
                'exclude_regex',
        )):
            raise IOError

        if 'exclude_regex' in data:
            result.exclude_files = data['exclude_regex']
        else:
            result.exclude_files = data['exclude']['files']
            result.exclude_lines = data['exclude']['lines']

        # In v0.12.7 the `--word-list` option got added
        automaton = None
        if 'word_list' in data:
            result.word_list_file = data['word_list']['file']
            result.word_list_hash = data['word_list']['hash']

            if result.word_list_file:
                # Always ignore the existing `data['word_list']['hash']`
                # The difference will show whenever the word list changes
                automaton, result.word_list_hash = build_automaton(
                    result.word_list_file)

        # In v0.14.0 the `--custom-plugins` option got added
        result.custom_plugin_paths = tuple(data.get('custom_plugin_paths', ()))

        result.plugins = tuple(
            initialize.from_plugin_classname(
                plugin_classname=plugin.pop('name'),
                custom_plugin_paths=result.custom_plugin_paths,
                exclude_lines_regex=result.exclude_lines,
                automaton=automaton,
                should_verify_secrets=False,
                **plugin) for plugin in data['plugins_used'])

        for filename in data['results']:
            result.data[filename] = {}

            for item in data['results'][filename]:
                secret = PotentialSecret(
                    item['type'],
                    filename,
                    secret='will be replaced',
                    lineno=item['line_number'],
                    is_secret=item.get('is_secret'),
                )
                secret.secret_hash = item['hashed_secret']
                result.data[filename][secret] = secret

        result.version = (data['version'] if 'version' in data else '0.0.0')

        return result
예제 #8
0
    def test_return_none_if_not_base_plugin(self):
        plugin = initialize.from_plugin_classname('log', )

        assert not plugin
예제 #9
0
 def test_fails_if_not_base_plugin(self):
     with pytest.raises(TypeError):
         initialize.from_plugin_classname(
             'log',
         )
예제 #10
0
 def test_fails_if_not_base_plugin(self):
     with pytest.raises(TypeError):
         initialize.from_plugin_classname(
             plugin_classname='NotABasePlugin',
             custom_plugin_paths=(),
         )
예제 #11
0
from detect_secrets.core.secrets_collection import SecretsCollection
from detect_secrets.core.potential_secret import PotentialSecret
from detect_secrets.plugins.common.initialize import from_plugin_classname

from .base import Tool, Issue, AccessIssue, UnknownIssue


class DetectSecretsIssue(Issue):
    tool = 'secrets'
    pylint_type = 'W'


PLUGINS = [
    from_plugin_classname(
        _plugin.classname, (),
        **dict([(
            _arg[0][2:].replace('-', '_'),
            _arg[1],
        ) for _arg in _plugin.related_args]))
    for _plugin in get_all_plugin_descriptors(())
]

DESCRIPTION = 'Possible secret detected: {description}'


def plugin_code(plugin):
    return plugin.__class__.__name__


class DetectSecretsTool(Tool):
    """
    The secrets tool attempts to detect secrets (keys, passwords, etc) that are