def potential_secret_factory(
    type_='type',
    filename='filename',
    secret='secret',
    lineno=1,
):
    """This is only marginally better than creating PotentialSecret objects directly,
    because of the default values.
    """
    return PotentialSecret(type_, filename, secret, lineno)
    def get_secret():
        """Generates a random secret, used for testing.

        :rtype: dict
        """
        random_number = random.randint(0, 500)
        return {
            'hashed_secret': PotentialSecret.hash_secret(str(random_number)),
            'line_number': random_number,
            'type': 'Test Type',
        }
    def analyze_string_content(self, string, line_num, filename):
        output = {}

        for identifier in self.secret_generator(string):
            secret = PotentialSecret(
                self.secret_type,
                filename,
                identifier,
                line_num,
            )
            output[secret] = secret

        return output
    def test_rolled_creds(self):
        """Same line, different secret"""
        new_findings = secrets_collection_factory([
            {
                'secret': 'secret_new',
            },
        ])
        baseline = secrets_collection_factory([
            {
                'secret': 'secret',
            },
        ])

        backup_baseline = baseline.data.copy()
        results = get_secrets_not_in_baseline(new_findings, baseline)

        assert len(results.data['filename']) == 1

        secretA = PotentialSecret('type', 'filename', 'secret_new', 1)
        assert results.data['filename'][secretA].secret_hash == \
            PotentialSecret.hash_secret('secret_new')
        assert baseline.data == backup_baseline
    def test_new_secret_line_old_file(self):
        """Same file, new line with potential secret"""
        new_findings = secrets_collection_factory([
            {
                'secret': 'secret1',
                'lineno': 1,
            },
        ])
        baseline = secrets_collection_factory([
            {
                'secret': 'secret2',
                'lineno': 2,
            },
        ])

        backup_baseline = baseline.data.copy()
        results = get_secrets_not_in_baseline(new_findings, baseline)

        assert len(results.data['filename']) == 1
        secretA = PotentialSecret('type', 'filename', 'secret1', 1)
        assert results.data['filename'][secretA].secret_hash == \
            PotentialSecret.hash_secret('secret1')
        assert baseline.data == backup_baseline
    def get_secret(self, filename, secret, type_=None):
        """Checks to see whether a secret is found in the collection.

        :type filename: str
        :param filename: the file to search in.

        :type secret: str
        :param secret: secret hash of secret to search for.

        :type type_: str
        :param type_: type of secret, if known.

        :rtype: PotentialSecret|None
        """
        if filename not in self.data:
            return None

        if type_:
            # Optimized lookup, because we know the type of secret
            # (and therefore, its hash)
            tmp_secret = PotentialSecret(type_,
                                         filename,
                                         secret='will be overriden')
            tmp_secret.secret_hash = secret

            if tmp_secret in self.data[filename]:
                return self.data[filename][tmp_secret]

            return None

        # NOTE: We can only optimize this, if we knew the type of secret.
        # Otherwise, we need to iterate through the set and find out.
        for obj in self.data[filename]:
            if obj.secret_hash == secret:
                return obj

        return None
Example #7
0
    def analyze_string_content(self, string, line_num, filename):
        """Searches string for custom pattern, and captures all high entropy strings that
        match self.regex, with a limit defined as self.entropy_limit.
        """
        output = {}

        for result in self.secret_generator(string):
            if self.is_secret_false_positive(result):
                continue

            secret = PotentialSecret(self.secret_type, filename, result,
                                     line_num)
            output[secret] = secret

        return output
Example #8
0
    def analyze_string_content(self, string, line_num, filename):
        output = {}
        if (self.keyword_exclude and self.keyword_exclude.search(string)):
            return output
        for identifier in self.secret_generator(
                string,
                filetype=determine_file_type(filename),
        ):
            if self.is_secret_false_positive(identifier):
                continue
            secret = PotentialSecret(
                self.secret_type,
                filename,
                identifier,
                line_num,
            )
            output[secret] = secret

        return output
    def _get_baseline_dict(self, gmtime):
        # They are all the same secret, so they should all have the same secret hash.
        secret_hash = PotentialSecret.hash_secret('secret')

        return {
            'generated_at': strftime('%Y-%m-%dT%H:%M:%SZ', gmtime),
            'plugins_used': [
                {
                    'name': 'HexHighEntropyString',
                    'hex_limit': 3,
                },
                {
                    'name': 'PrivateKeyDetector',
                },
            ],
            'results': {
                'fileA': [
                    # Line numbers should be sorted, for better readability
                    {
                        'type': 'B',
                        'is_verified': False,
                        'line_number': 2,
                        'hashed_secret': secret_hash,
                    },
                    {
                        'type': 'A',
                        'is_verified': False,
                        'line_number': 3,
                        'hashed_secret': secret_hash,
                    },
                ],
                'fileB': [
                    {
                        'type': 'C',
                        'is_verified': False,
                        'line_number': 1,
                        'hashed_secret': secret_hash,
                    },
                ],
            },
            'version': VERSION,
        }
def _create_baseline_template(has_result, use_private_key_scan):
    base64_secret = 'c3VwZXIgbG9uZyBzdHJpbmcgc2hvdWxkIGNhdXNlIGVub3VnaCBlbnRyb3B5'
    baseline = {
        'generated_at': 'does_not_matter',
        'plugins_used': [
            {
                'name': 'HexHighEntropyString',
                'hex_limit': 3,
            },
            {
                'name': 'Base64HighEntropyString',
                'base64_limit': 4.5,
            },
            {
                'name': 'PrivateKeyDetector',
            },
        ],
        'results': {
            'test_data/files/file_with_secrets.py': [
                {
                    'type': 'Base64 High Entropy String',
                    'is_secret': True,
                    'is_verified': False,
                    'line_number': 3,
                    'hashed_secret': PotentialSecret.hash_secret(base64_secret),
                },
            ],
        },
        'version': VERSION,
    }

    if not use_private_key_scan:
        baseline['plugins_used'].pop(-1)

    if not has_result:
        baseline['results'] = {}

    return baseline
 def analyze(self, f, filename):
     password_secret = PotentialSecret('Password', filename, f.read().strip(), 2)
     return {
         password_secret: password_secret,
     }
 def analyze(self, f, filename):
     # We're not testing the plugin's ability to analyze secrets, so
     # it doesn't matter what we return
     secret = PotentialSecret('mock file value type', filename, f.read().strip(), 2)
     return {secret: secret}
 def analyze(self, f, filename):
     # We're not testing the plugin's ability to analyze secrets, so
     # it doesn't matter what we return
     secret = PotentialSecret('mock fixed value type', filename, 'asdf', 1)
     return {secret: secret}
    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 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')
            plugins.append(
                initialize.from_plugin_classname(
                    plugin_classname,
                    exclude_lines_regex=result.exclude_lines,
                    automaton=automaton,
                    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