@@ -92,6 +92,70 @@ def test_warn_mode_returns_missing(self, tmp_path: Path) -> None:
9292 assert result .status == SignatureStatus .MISSING
9393
9494
95+ class TestSignatureVerificationModeWarn :
96+ """WARN mode verifies offline so the sigstore TUF refresh is skipped."""
97+
98+ def test_warn_mode_uses_offline_verifier (self , tmp_path : Path ) -> None :
99+ wheel = tmp_path / "plugin-1.0.0.whl"
100+ wheel .write_bytes (b"fake wheel content" )
101+ bundle = tmp_path / "plugin-1.0.0.whl.sigstore"
102+ bundle .write_bytes (b'{"fake": "bundle"}' )
103+
104+ mock_verifier_cls = MagicMock ()
105+ mock_bundle_cls = MagicMock ()
106+ mock_all_of_cls = MagicMock ()
107+ mock_oidc_issuer_cls = MagicMock ()
108+ mock_gh_repo_cls = MagicMock ()
109+
110+ mock_verifier_cls .production .return_value .verify_artifact .return_value = None
111+ mock_bundle_cls .from_json .return_value = MagicMock ()
112+
113+ with (
114+ patch ("ggshield.core.plugin.signature.Verifier" , mock_verifier_cls ),
115+ patch ("ggshield.core.plugin.signature.Bundle" , mock_bundle_cls ),
116+ patch ("ggshield.core.plugin.signature.AllOf" , mock_all_of_cls ),
117+ patch ("ggshield.core.plugin.signature.OIDCIssuer" , mock_oidc_issuer_cls ),
118+ patch (
119+ "ggshield.core.plugin.signature.GitHubWorkflowRepository" ,
120+ mock_gh_repo_cls ,
121+ ),
122+ ):
123+ verify_wheel_signature (wheel , SignatureVerificationMode .WARN )
124+
125+ # The TUF refresh runs inside Verifier.production() unless offline=True
126+ # is passed; --allow-unsigned must opt into offline verification.
127+ mock_verifier_cls .production .assert_called_once_with (offline = True )
128+
129+ def test_strict_mode_uses_online_verifier (self , tmp_path : Path ) -> None :
130+ wheel = tmp_path / "plugin-1.0.0.whl"
131+ wheel .write_bytes (b"fake wheel content" )
132+ bundle = tmp_path / "plugin-1.0.0.whl.sigstore"
133+ bundle .write_bytes (b'{"fake": "bundle"}' )
134+
135+ mock_verifier_cls = MagicMock ()
136+ mock_bundle_cls = MagicMock ()
137+ mock_all_of_cls = MagicMock ()
138+ mock_oidc_issuer_cls = MagicMock ()
139+ mock_gh_repo_cls = MagicMock ()
140+
141+ mock_verifier_cls .production .return_value .verify_artifact .return_value = None
142+ mock_bundle_cls .from_json .return_value = MagicMock ()
143+
144+ with (
145+ patch ("ggshield.core.plugin.signature.Verifier" , mock_verifier_cls ),
146+ patch ("ggshield.core.plugin.signature.Bundle" , mock_bundle_cls ),
147+ patch ("ggshield.core.plugin.signature.AllOf" , mock_all_of_cls ),
148+ patch ("ggshield.core.plugin.signature.OIDCIssuer" , mock_oidc_issuer_cls ),
149+ patch (
150+ "ggshield.core.plugin.signature.GitHubWorkflowRepository" ,
151+ mock_gh_repo_cls ,
152+ ),
153+ ):
154+ verify_wheel_signature (wheel , SignatureVerificationMode .STRICT )
155+
156+ mock_verifier_cls .production .assert_called_once_with (offline = False )
157+
158+
95159class TestBundleVerification :
96160 """Tests for bundle verification with mocked sigstore."""
97161
0 commit comments