Exemple #1
0
def configure_plugins():
    with transient_settings({
            'plugins_used': [{
                'name': 'PrivateKeyDetector'
            }],
    }):
        yield
Exemple #2
0
    def test_saves_to_baseline():
        # We create an empty baseline, with customized settings.
        # This way, we expect the engine to use the settings configured by the baseline,
        # but have the results replaced by the new scan.
        with transient_settings({
                'plugins_used': [
                    {
                        'name': 'Base64HighEntropyString',
                        'limit': 4.5,
                    },
                ],
        }):
            secrets = SecretsCollection()
            old_secrets = baseline.format_for_output(secrets)

        with mock_printer(
                main_module) as printer, tempfile.NamedTemporaryFile() as f:
            baseline.save_to_file(old_secrets, f.name)
            f.seek(0)

            # We also test setting the root directory through this test.
            main_module.main(['scan', 'test_data', '--baseline', f.name])

            f.seek(0)
            new_secrets = json.loads(f.read())
            assert not secrets.exactly_equals(
                baseline.load(new_secrets, f.name))
            assert new_secrets['plugins_used'] == [
                {
                    'name': 'Base64HighEntropyString',
                    'limit': 4.5,
                },
            ]
            assert not printer.message
def configure_settings():
    with transient_settings({
            'plugins_used': [{
                'name': 'Base64HighEntropyString',
                'limit': 4.5
            }],
    }):
        yield
Exemple #4
0
 def test_ignore_case():
     with transient_settings({
             'plugins_used': [{
                 'name': 'KeywordDetector',
             }],
     }):
         assert list(
             scan_line('os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"'))
Exemple #5
0
def configure_plugins():
    with transient_settings({
            'plugins_used': [
                {
                    'name': 'BasicAuthDetector',
                },
            ],
    }):
        yield
Exemple #6
0
    def test_cli_overrides_stdin():
        with transient_settings({
                'plugins_used': [
                    {
                        'name': 'AWSKeyDetector',
                    },
                ],
        }), mock_stdin('AKIATESTTESTTESTTEST', ), mock_printer(
                main_module) as printer:
            assert main_module.main(['scan', '--string', 'blah']) == 0

            assert printer.message.strip() == 'AWSKeyDetector: False'
Exemple #7
0
 def test_failed_high_entropy_string():
     with transient_settings({
             'plugins_used': [
                 {
                     'name': 'Base64HighEntropyString',
                     'limit': 5.0,
                 },
             ],
     }):
         assert scan_adhoc_string('bangbangintotheroom').splitlines() == [
             'Base64HighEntropyString: False (3.326)',
         ]
Exemple #8
0
    def test_supports_stdin():
        with transient_settings({
                'plugins_used': [
                    {
                        'name': 'AWSKeyDetector',
                    },
                ],
        }), mock_stdin('AKIATESTTESTTESTTEST', ), mock_printer(
                main_module) as printer, disable_gibberish_filter():
            assert main_module.main(['scan', '--string']) == 0

            assert printer.message.strip(
            ) == 'AWSKeyDetector: True  (unverified)'
Exemple #9
0
    def test_analyze_javascript_negatives(line):
        with transient_settings({
                'plugins_used': [{
                    'name': 'KeywordDetector',
                }],
        }):
            assert list(scan_line(line))

            with tempfile.NamedTemporaryFile(suffix='.js') as f:
                f.write(line.encode('utf-8'))
                f.seek(0)

                assert not list(scan_file(f.name))
Exemple #10
0
def test_load_from_baseline():
    with transient_settings({
            'filters_used': [{
                'path':
                'detect_secrets.filters.gibberish.should_exclude_secret',
                'model':
                os.path.join(filters.gibberish.__path__[0], 'rfc.model'),
                'file_hash':
                '00b672f709e9bf51fe2e09abe247ac3b6415d645',
                'limit':
                3.7,
            }],
    }):
        assert filters.gibberish.should_exclude_secret('clearly-not-a-secret')
def test_load_from_baseline():
    with transient_settings({
            'filters_used': [{
                'path':
                'detect_secrets.filters.wordlist.should_exclude_secret',
                'min_length':
                8,
                'file_name':
                'test_data/word_list.txt',
                'file_hash':
                '116598304e5b33667e651025bcfed6b9a99484c7',
            }],
    }):
        assert filters.wordlist.should_exclude_secret('testPass') is True
Exemple #12
0
 def test_basic():
     with transient_settings({
             'plugins_used': [
                 {
                     'name': 'AWSKeyDetector',
                 },
                 {
                     'name': 'PrivateKeyDetector',
                 },
             ],
     }):
         assert scan_adhoc_string('AKIATESTTESTTESTTEST').splitlines() == [
             'AWSKeyDetector    : True',
             'PrivateKeyDetector: False',
         ]
def baseline_file():
    # Create our own SecretsCollection manually, so that we have fine-tuned control.
    first_content = textwrap.dedent(f"""
        url = {url_format.format(first_secret)}
        example = {url_format.format(random_secret)}
        link = {url_format.format(first_secret)}
    """)[1:]
    second_content = textwrap.dedent(f"""
        url = {url_format.format(second_secret)}
        example = {url_format.format(random_secret)}
    """)[1:]

    with create_file_with_content(first_content) as first_file, \
            create_file_with_content(second_content) as second_file, \
            tempfile.NamedTemporaryFile() as baseline_file, \
            transient_settings({
                'plugins_used': [
                    {'name': 'BasicAuthDetector'},
                    {'name': 'JwtTokenDetector'},

                ],
            }):
        secrets = SecretsCollection()
        secrets.scan_file(first_file)
        secrets.scan_file(second_file)
        labels = {
            (first_file, BasicAuthDetector.secret_type, 1): True,
            (first_file, BasicAuthDetector.secret_type, 2): None,
            (first_file, BasicAuthDetector.secret_type, 3): True,
            (second_file, JwtTokenDetector.secret_type, 1): True,
            (second_file, BasicAuthDetector.secret_type, 1): False,
            (second_file, BasicAuthDetector.secret_type, 2): False,
        }
        for item in secrets:
            _, secret = item
            secret.is_secret = labels[(secret.filename, secret.type,
                                       secret.line_number)]
        baseline.save_to_file(secrets, baseline_file.name)
        baseline_file.seek(0)
        yield baseline_file.name
Exemple #14
0
    def run(self,
            root_folder: str,
            external_checks_dir: Optional[List[str]] = None,
            files: Optional[List[str]] = None,
            runner_filter: RunnerFilter = RunnerFilter(),
            collect_skip_comments: bool = True) -> Report:
        current_dir = os.path.dirname(os.path.realpath(__file__))
        secrets = SecretsCollection()
        with transient_settings({
                # Only run scans with only these plugins.
                'plugins_used':
            [{
                'name': 'AWSKeyDetector'
            }, {
                'name': 'ArtifactoryDetector'
            }, {
                'name': 'AzureStorageKeyDetector'
            }, {
                'name': 'BasicAuthDetector'
            }, {
                'name': 'CloudantDetector'
            }, {
                'name': 'IbmCloudIamDetector'
            }, {
                'name': 'MailchimpDetector'
            }, {
                'name': 'PrivateKeyDetector'
            }, {
                'name': 'SlackDetector'
            }, {
                'name': 'SoftlayerDetector'
            }, {
                'name': 'SquareOAuthDetector'
            }, {
                'name': 'StripeDetector'
            }, {
                'name': 'TwilioKeyDetector'
            }, {
                'name': 'EntropyKeywordCombinator',
                'path':
                f'file://{current_dir}/plugins/entropy_keyword_combinator.py',
                'limit': ENTROPY_KEYWORD_LIMIT
            }]
        }) as settings:
            report = Report(self.check_type)
            # Implement non IaC files (including .terraform dir)
            files_to_scan = files or []
            excluded_paths = (
                runner_filter.excluded_paths
                or []) + ignored_directories + [DEFAULT_EXTERNAL_MODULES_DIR]
            if root_folder:
                for root, d_names, f_names in os.walk(root_folder):
                    filter_ignored_paths(root, d_names, excluded_paths)
                    filter_ignored_paths(root, f_names, excluded_paths)
                    for file in f_names:
                        if file not in PROHIBITED_FILES and f".{file.split('.')[-1]}" in SUPPORTED_FILE_EXTENSIONS:
                            files_to_scan.append(os.path.join(root, file))
            logging.info(
                f'Secrets scanning will scan {len(files_to_scan)} files')

            settings.disable_filters(
                *['detect_secrets.filters.heuristic.is_indirect_reference'])

            Runner._scan_files(files_to_scan, secrets)

            for _, secret in iter(secrets):
                check_id = SECRET_TYPE_TO_ID.get(secret.type)
                bc_check_id = bc_integration.ckv_to_bc_id_mapping.get(
                    check_id) if bc_integration.ckv_to_bc_id_mapping else None
                if not check_id:
                    continue
                if runner_filter.checks and not runner_filter.should_run_check(
                        check_id, bc_check_id):
                    continue
                result: _CheckResult = {'result': CheckResult.FAILED}
                line_text = linecache.getline(secret.filename,
                                              secret.line_number)
                if line_text != "" and len(line_text.split(
                )) > 0 and line_text.split()[0] == 'git_commit':
                    continue
                result = self.search_for_suppression(
                    check_id=check_id,
                    bc_check_id=bc_check_id,
                    secret=secret,
                    runner_filter=runner_filter,
                ) or result
                report.add_resource(f'{secret.filename}:{secret.secret_hash}')
                report.add_record(
                    Record(check_id=check_id,
                           bc_check_id=bc_check_id,
                           check_name=secret.type,
                           check_result=result,
                           code_block=[(secret.line_number, line_text)],
                           file_path=
                           f'/{os.path.relpath(secret.filename, root_folder)}',
                           file_line_range=[
                               secret.line_number, secret.line_number + 1
                           ],
                           resource=secret.secret_hash,
                           check_class=None,
                           evaluations=None,
                           file_abs_path=os.path.abspath(secret.filename)))

            return report