Beispiel #1
0
def test_baseline_filters_out_known_secrets():
    secrets = SecretsCollection()
    secrets.scan_file('test_data/each_secret.py')

    with tempfile.NamedTemporaryFile() as f:
        baseline.save_to_file(secrets, f.name)
        f.seek(0)

        # This succeeds, because all the secrets are known.
        assert_commit_succeeds([
            'test_data/each_secret.py',
            '--baseline',
            f.name,
        ])

    # Remove one arbitrary secret, so that it won't be the full set.
    secrets.data['test_data/each_secret.py'].pop()

    with tempfile.NamedTemporaryFile() as f:
        baseline.save_to_file(secrets, f.name)
        f.seek(0)

        # Test that it isn't the case that a baseline is provided, and everything passes.
        # import pdb; pdb.set_trace()
        assert_commit_blocked([
            'test_data/each_secret.py',
            '--baseline',
            f.name,
        ])
Beispiel #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 run_logic(secretsA: SecretsCollection, secretsB: SecretsCollection):
    with tempfile.NamedTemporaryFile() as f, tempfile.NamedTemporaryFile(
    ) as g:
        baseline.save_to_file(secretsA, f.name)
        baseline.save_to_file(secretsB, g.name)

        main(['audit', '--diff', f.name, g.name])
def test_no_divide_by_zero(secret):
    secrets = SecretsCollection()
    secrets['file'].add(secret)
    with tempfile.NamedTemporaryFile() as f:
        baseline.save_to_file(secrets, f.name)
        f.seek(0)

        main(['audit', f.name, '--stats', '--json'])
Beispiel #5
0
    def test_modifies_baseline(self, modified_baseline):
        with tempfile.NamedTemporaryFile() as f:
            baseline.save_to_file(modified_baseline, f.name)

            assert_commit_blocked_with_diff_exit_code([
                self.FILENAME,
                '--baseline',
                f.name,
            ])
Beispiel #6
0
    def test_does_not_modify_slim_baseline(self, modified_baseline):
        with tempfile.NamedTemporaryFile() as f:
            baseline.save_to_file(
                baseline.format_for_output(modified_baseline, is_slim_mode=True),
                f.name,
            )

            assert_commit_succeeds([
                self.FILENAME,
                '--baseline',
                f.name,
            ])
Beispiel #7
0
def main(argv: Optional[List[str]] = None) -> int:
    try:
        args = parse_args(argv)
    except ValueError:
        return 1

    if args.verbose:  # pragma: no cover
        log.set_debug_level(args.verbose)

    # Find all secrets in files to be committed
    secrets = SecretsCollection()
    for filename in args.filenames:
        secrets.scan_file(filename)

    new_secrets = secrets
    if args.baseline:
        new_secrets = secrets - args.baseline

    if new_secrets:
        pretty_print_diagnostics(new_secrets)
        return 1

    if not args.baseline:
        return 0

    # Only attempt baseline modifications if we don't find any new secrets.
    is_modified = should_update_baseline(
        args.baseline,
        scanned_results=secrets,
        filelist=args.filenames,
        baseline_version=args.baseline_version,
    )

    if is_modified:
        if args.baseline_version != VERSION:
            with open(args.baseline_filename) as f:
                old_baseline = json.loads(f.read())

            # Override the results, because this has been updated in `should_update_baseline`.
            old_baseline['results'] = args.baseline.json()

            args.baseline = baseline.upgrade(old_baseline)

        baseline.save_to_file(args.baseline, filename=args.baseline_filename)
        print(
            'The baseline file was updated.\n'
            'Probably to keep line numbers of secrets up-to-date.\n'
            'Please `git add {}`, thank you.\n\n'.format(
                args.baseline_filename), )
        return 3

    return 0
Beispiel #8
0
    def get_baseline_file(self, formatter=baseline.format_for_output):
        secrets = SecretsCollection()
        secrets.scan_file(self.FILENAME)

        with tempfile.NamedTemporaryFile() as f:
            with mock.patch('detect_secrets.core.baseline.VERSION', '0.0.1'):
                data = formatter(secrets)

            # Simulating old version
            data['plugins_used'][0]['base64_limit'] = data['plugins_used'][0].pop('limit')
            baseline.save_to_file(data, f.name)

            yield f
Beispiel #9
0
def test_only_verified_overrides_baseline_settings(parser):
    secrets = SecretsCollection()
    with tempfile.NamedTemporaryFile() as f, transient_settings({
            'filters_used':
        [{
            'path':
            'detect_secrets.filters.common.is_ignored_due_to_verification_policies',
            'min_level': VerifiedResult.UNVERIFIED.value,
        }],
    }):
        baseline.save_to_file(secrets, f.name)
        f.seek(0)

        parser.parse_args(['scan', '--baseline', f.name, '--only-verified'])
        assert get_settings().filters[
            'detect_secrets.filters.common.is_ignored_due_to_verification_policies'][
                'min_level'] == VerifiedResult.VERIFIED_TRUE.value
Beispiel #10
0
def test_no_verify_overrides_baseline_settings(parser):
    secrets = SecretsCollection()
    with tempfile.NamedTemporaryFile() as f, transient_settings({
            'filters_used':
        [{
            'path':
            'detect_secrets.filters.common.is_ignored_due_to_verification_policies',
            'min_level': VerifiedResult.UNVERIFIED.value,
        }],
    }):
        baseline.save_to_file(secrets, f.name)
        f.seek(0)

        parser.parse_args(['scan', '--baseline', f.name, '--no-verify'])
        for filter_path in get_settings().filters:
            assert filter_path.rsplit(
                '.')[-1] != 'is_ignored_due_to_verification_policies'
def labelled_secrets():
    # Create our own SecretsCollection manually, so that we have fine-tuned control.
    secrets = SecretsCollection()
    secrets['fileA'] = {
        potential_secret_factory(),
        potential_secret_factory(is_secret=True),
        potential_secret_factory(is_secret=False),
    }
    secrets['fileB'] = {
        potential_secret_factory(is_secret=False),
    }

    with tempfile.NamedTemporaryFile() as f:
        baseline.save_to_file(secrets, f.name)
        f.seek(0)

        yield f.name
Beispiel #12
0
    def test_success(parser):
        # Ensure it serializes accordingly.
        parser.parse_args(['-p', 'testing/plugins.py'])

        with tempfile.NamedTemporaryFile() as f:
            baseline.save_to_file(SecretsCollection(), f.name)
            f.seek(0)

            get_settings().clear()
            plugins.util.get_mapping_from_secret_type_to_class.cache_clear()
            assert 'HippoDetector' not in get_settings().plugins

            parser.parse_args(['--baseline', f.name])
            assert get_settings().plugins['HippoDetector'] == {
                'path': f'file://{os.path.abspath("testing/plugins.py")}',
            }
            assert plugins.initialize.from_plugin_classname('HippoDetector')
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
Beispiel #14
0
def run_logic(
    secrets: SecretsCollection,
    input: Optional[str] = None,
) -> SecretsCollection:
    """
    :param input: if provided, will automatically quit at the end of input string.
        otherwise, will assert that no user input is requested.
    """
    with tempfile.NamedTemporaryFile() as f:
        baseline.save_to_file(secrets, f.name)
        f.seek(0)

        with mock.patch('detect_secrets.audit.io.input') as m:
            if input is not None:
                m.side_effect = list(input) + ['q']

            main(['audit', f.name])

            if input is None:
                assert not m.called

        return baseline.load(baseline.load_from_file(f.name), f.name)