diff --git a/changelog.d/20250507_145529_achille.mascia_add_nhi_option.md b/changelog.d/20250507_145529_achille.mascia_add_nhi_option.md new file mode 100644 index 0000000000..8931219206 --- /dev/null +++ b/changelog.d/20250507_145529_achille.mascia_add_nhi_option.md @@ -0,0 +1,42 @@ + + + + +### Added + +- Added a new section in ggshield's outputs (text and json) to notify if a secret is in one of the accounts' secrets managers. + + + + + diff --git a/doc/schemas/secret.json b/doc/schemas/secret.json index 7ba8ff79fc..2ee57b101e 100644 --- a/doc/schemas/secret.json +++ b/doc/schemas/secret.json @@ -96,6 +96,9 @@ "known_secret": { "type": "boolean" }, + "secret_vaulted": { + "type": "boolean" + }, "occurrences": { "type": "array", "items": { diff --git a/ggshield/verticals/secret/output/schemas.py b/ggshield/verticals/secret/output/schemas.py index 786c0e537d..25a9f61dbf 100644 --- a/ggshield/verticals/secret/output/schemas.py +++ b/ggshield/verticals/secret/output/schemas.py @@ -22,6 +22,7 @@ class FlattenedPolicyBreak(BaseSchema): incident_details = fields.Nested(SecretIncidentSchema) known_secret = fields.Bool(required=True, dump_default=False) ignore_reason = fields.Nested(IgnoreReasonSchema, dump_default=None) + secret_vaulted = fields.Bool(required=True, dump_default=False) class JSONResultSchema(BaseSchema): diff --git a/ggshield/verticals/secret/output/secret_json_output_handler.py b/ggshield/verticals/secret/output/secret_json_output_handler.py index bb74896931..1796882e11 100644 --- a/ggshield/verticals/secret/output/secret_json_output_handler.py +++ b/ggshield/verticals/secret/output/secret_json_output_handler.py @@ -141,6 +141,8 @@ def serialized_secret( secrets[0].ignore_reason ) + if secrets[0].is_vaulted: + flattened_dict["secret_vaulted"] = secrets[0].is_vaulted for secret in secrets: flattened_dict["occurrences"].extend(self.serialize_secret_matches(secret)) diff --git a/ggshield/verticals/secret/output/secret_sarif_output_handler.py b/ggshield/verticals/secret/output/secret_sarif_output_handler.py index 384d7da893..1db6f05009 100644 --- a/ggshield/verticals/secret/output/secret_sarif_output_handler.py +++ b/ggshield/verticals/secret/output/secret_sarif_output_handler.py @@ -83,6 +83,7 @@ def _create_sarif_result_dict( markdown_message = f"Secret detected: [{secret.detector_display_name}]({secret.documentation_url})" else: markdown_message = f"Secret detected: {secret.detector_display_name}" + markdown_message += f"\nSecret in Secrets Manager: {secret.is_vaulted}" markdown_message += f"\nMatches:\n{matches_li}" # Create dict diff --git a/ggshield/verticals/secret/output/secret_text_output_handler.py b/ggshield/verticals/secret/output/secret_text_output_handler.py index 526512ffc3..2f79ab1358 100644 --- a/ggshield/verticals/secret/output/secret_text_output_handler.py +++ b/ggshield/verticals/secret/output/secret_text_output_handler.py @@ -305,8 +305,9 @@ def secret_header( {start_line} Secret detected: {secret_type}{validity_msg} {indent}Occurrences: {number_occurrences} {indent}Known by GitGuardian dashboard: {"YES" if known_secret else "NO"} -{indent}Incident URL: {secrets[0].incident_url if known_secret and secret.incident_url else "N/A"} +{indent}Incident URL: {secret.incident_url if known_secret and secret.incident_url else "N/A"} {indent}Secret SHA: {ignore_sha} +{indent}Secret in Secrets Manager: {secret.is_vaulted} """ if secret.documentation_url is not None: message += f"{indent}Detector documentation: {secret.documentation_url}\n" diff --git a/ggshield/verticals/secret/secret_scan_collection.py b/ggshield/verticals/secret/secret_scan_collection.py index 09f53c61dd..61f0903f10 100644 --- a/ggshield/verticals/secret/secret_scan_collection.py +++ b/ggshield/verticals/secret/secret_scan_collection.py @@ -93,6 +93,7 @@ class Secret: matches: List[ExtendedMatch] ignore_reason: Optional[IgnoreReason] diff_kind: Optional[DiffKind] + is_vaulted: bool @property def policy(self) -> str: @@ -199,6 +200,7 @@ def from_scan_result( ], ignore_reason=ignore_reason, diff_kind=policy_break.diff_kind, + is_vaulted=policy_break.is_vaulted, ) for policy_break, ignore_reason in to_keep ] diff --git a/pdm.lock b/pdm.lock index 7dfd998e6f..b7d22e9d7e 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev", "standalone", "tests"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:e1572d77668f4d224a203310e8d9e8646a32e17b0d8da9785ce21a23a0e15cfc" +content_hash = "sha256:ec66df3fa039c3b99f863d7d5f60d2cf6de885fedd0e88324f79ce89e32da221" [[metadata.targets]] requires_python = ">=3.9" @@ -1624,6 +1624,9 @@ files = [ name = "pygitguardian" version = "1.21.0" requires_python = ">=3.8" +git = "https://github.com/GitGuardian/py-gitguardian.git" +ref = "2f6da32f01c6e2dc5eaf4eccf9104a846ea7ca70" +revision = "2f6da32f01c6e2dc5eaf4eccf9104a846ea7ca70" summary = "Python Wrapper for GitGuardian's API -- Scan security policy breaks everywhere" groups = ["default"] dependencies = [ @@ -1633,10 +1636,6 @@ dependencies = [ "setuptools>=70.1.0", "typing-extensions", ] -files = [ - {file = "pygitguardian-1.21.0-py3-none-any.whl", hash = "sha256:f19c74395d845207dd6465ce6209a24985b5865b4d9056269f5b5a9346d7f0f1"}, - {file = "pygitguardian-1.21.0.tar.gz", hash = "sha256:e934ab00ff8ead8c6b149dc358d594ba3de41e68a93c10c95d0b72faf9506dfc"}, -] [[package]] name = "pygments" diff --git a/pyproject.toml b/pyproject.toml index 7de2969a85..4c4b2792e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ dependencies = [ "marshmallow~=3.18.0", "marshmallow-dataclass~=8.5.8", "oauthlib~=3.2.1", - "pygitguardian~=1.21.0", + "pygitguardian @ git+https://github.com/GitGuardian/py-gitguardian.git@2f6da32f01c6e2dc5eaf4eccf9104a846ea7ca70", "pyjwt~=2.6.0", "python-dotenv~=0.21.0", "pyyaml~=6.0.1", diff --git a/tests/factories.py b/tests/factories.py index c54dcf06ed..bb6a29da42 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -67,6 +67,7 @@ class Meta: known_secret = False incident_url = None is_excluded = False + is_vaulted = False exclude_reason = None diff_kind = None content = factory.Faker("text") @@ -109,3 +110,4 @@ class Meta: matches = [] ignore_reason = None diff_kind = None + is_vaulted = False diff --git a/tests/unit/verticals/secret/output/snapshots/snap_test_text_output.py b/tests/unit/verticals/secret/output/snapshots/snap_test_text_output.py index a89815e86f..2296bfd0b0 100644 --- a/tests/unit/verticals/secret/output/snapshots/snap_test_text_output.py +++ b/tests/unit/verticals/secret/output/snapshots/snap_test_text_output.py @@ -15,6 +15,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -34,6 +35,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -55,6 +57,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -76,6 +79,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -95,6 +99,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -114,6 +119,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -135,6 +141,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -156,6 +163,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1 @@ @@ -175,6 +183,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +2 @@ @@ -194,6 +203,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +2 @@ @@ -215,6 +225,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +2 @@ @@ -236,6 +247,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 38d9d3464520ed68f18d16e640a4a8b37ef5b17608b455267d100aa487ead314 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +2 @@ @@ -255,6 +267,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 1945f4a0c42abb19c1a420ddd09b4b4681249a3057c427b95f794b18595e7ffa + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1,29 @@ @@ -270,6 +283,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -289,6 +303,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 530e5a4a7ea00814db8845dd0cae5efaa4b974a3ce1c76d0384ba715248a5dc1 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/sendgrid_key 7 | +**********************+***************************************** @@ -307,6 +322,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 1945f4a0c42abb19c1a420ddd09b4b4681249a3057c427b95f794b18595e7ffa + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1,29 @@ @@ -322,6 +338,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -341,6 +358,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 530e5a4a7ea00814db8845dd0cae5efaa4b974a3ce1c76d0384ba715248a5dc1 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/sendgrid_key 7 | +bLaA/DCNPniBAiA0l//bzg+M3srIhm04xzLdR9Vb9IjPRlkvN074zdKDVwIhAKJb @@ -361,6 +379,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 1945f4a0c42abb19c1a420ddd09b4b4681249a3057c427b95f794b18595e7ffa + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1,29 @@ @@ -376,6 +395,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -395,6 +415,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 530e5a4a7ea00814db8845dd0cae5efaa4b974a3ce1c76d0384ba715248a5dc1 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/sendgrid_key 7 | +**********************+***************************************** @@ -415,6 +436,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 1945f4a0c42abb19c1a420ddd09b4b4681249a3057c427b95f794b18595e7ffa + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/facebook_access_token | @@ -0,0 +1,29 @@ @@ -430,6 +452,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -449,6 +472,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 530e5a4a7ea00814db8845dd0cae5efaa4b974a3ce1c76d0384ba715248a5dc1 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/sendgrid_key 7 | +bLaA/DCNPniBAiA0l//bzg+M3srIhm04xzLdR9Vb9IjPRlkvN074zdKDVwIhAKJb @@ -467,6 +491,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -493,6 +518,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -521,6 +547,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -549,6 +576,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 060bf63de122848f5efa122fe6cea504aae3b24cea393d887fdefa1529c6a02e + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/private_key_rsa | @@ -0,0 +1,29 @@ @@ -575,6 +603,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 2b5840babacb6f089ddcce1fe5a56b803f8b1f636c6f44cdbf14b0c77a194c93 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/github_access_token | @@ -0,0 +1 @@ @@ -592,6 +621,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 2b5840babacb6f089ddcce1fe5a56b803f8b1f636c6f44cdbf14b0c77a194c93 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/github_access_token | @@ -0,0 +1 @@ @@ -611,6 +641,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 2b5840babacb6f089ddcce1fe5a56b803f8b1f636c6f44cdbf14b0c77a194c93 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/github_access_token | @@ -0,0 +1 @@ @@ -630,6 +661,7 @@ Known by GitGuardian dashboard: NO Incident URL: N/A Secret SHA: 2b5840babacb6f089ddcce1fe5a56b803f8b1f636c6f44cdbf14b0c77a194c93 + Secret in Secrets Manager: False Detector documentation: https://docs.gitguardian.com/secrets-detection/secrets-detection-engine/detectors/specifics/github_access_token | @@ -0,0 +1 @@ diff --git a/tests/unit/verticals/secret/output/test_json_output.py b/tests/unit/verticals/secret/output/test_json_output.py index e26811bb73..deff5be912 100644 --- a/tests/unit/verticals/secret/output/test_json_output.py +++ b/tests/unit/verticals/secret/output/test_json_output.py @@ -652,3 +652,35 @@ def test_ignore_reason(ignore_reason, expected_output): parsed_incidents = json.loads(output)["entities_with_incidents"][0]["incidents"] assert parsed_incidents[0]["ignore_reason"] == expected_output + + +@pytest.mark.parametrize( + "is_vaulted", + (True, False), +) +def test_vaulted_secret(is_vaulted: bool): + """ + GIVEN an result + WHEN it is passed to the json output handler + THEN the vaulted_secret field is as expected + """ + + secret_config = SecretConfig() + scannable = ScannableFactory() + policy_break = PolicyBreakFactory(content=scannable.content, is_vaulted=is_vaulted) + result = Result.from_scan_result( + scannable, ScanResultFactory(policy_breaks=[policy_break]), secret_config + ) + + output_handler = SecretJSONOutputHandler(secret_config=secret_config, verbose=False) + + output = output_handler._process_scan_impl( + SecretScanCollection( + id="scan", + type="scan", + results=Results(results=[result], errors=[]), + ) + ) + + parsed_incidents = json.loads(output)["entities_with_incidents"][0]["incidents"] + assert parsed_incidents[0]["secret_vaulted"] == is_vaulted diff --git a/tests/unit/verticals/secret/output/test_sarif_output.py b/tests/unit/verticals/secret/output/test_sarif_output.py index 6bc3fc4924..ca37c5c309 100644 --- a/tests/unit/verticals/secret/output/test_sarif_output.py +++ b/tests/unit/verticals/secret/output/test_sarif_output.py @@ -301,6 +301,13 @@ def check_sarif_result( matched_text = get_content_from_region(content, region) actual_matches[match_name] = matched_text + # Check that the markdown message contains the correct is_vaulted information + markdown_message = sarif_result["message"]["markdown"] + expected_is_vaulted_text = f"Secret in Secrets Manager: {secret.is_vaulted}" + assert ( + expected_is_vaulted_text in markdown_message + ), f"Expected '{expected_is_vaulted_text}' in markdown message, but got: {markdown_message}" + if contains_incident_details: assert ( "properties" in sarif_result diff --git a/tests/unit/verticals/secret/output/test_text_output.py b/tests/unit/verticals/secret/output/test_text_output.py index 095c191769..178bf8fb38 100644 --- a/tests/unit/verticals/secret/output/test_text_output.py +++ b/tests/unit/verticals/secret/output/test_text_output.py @@ -264,3 +264,34 @@ def test_ignore_reason(ignore_reason): else: assert "Ignored:" in output assert ignore_reason.to_human_readable() in output + + +@pytest.mark.parametrize( + "is_vaulted", + (True, False), +) +def test_vaulted_secret(is_vaulted: bool): + """ + GIVEN a secret + WHEN it is passed to the text output handler + THEN the vaulted_secret field is displayed as expected + """ + + secret_config = SecretConfig() + scannable = ScannableFactory() + policy_break = PolicyBreakFactory(content=scannable.content, is_vaulted=is_vaulted) + result = Result.from_scan_result( + scannable, ScanResultFactory(policy_breaks=[policy_break]), secret_config + ) + + output_handler = SecretTextOutputHandler(secret_config=secret_config, verbose=False) + + output = output_handler._process_scan_impl( + SecretScanCollection( + id="scan", + type="scan", + results=Results(results=[result], errors=[]), + ) + ) + + assert f"Secret in Secrets Manager: {is_vaulted}" in output