@@ -55,6 +55,7 @@ def mock_github_webhook(self) -> Mock:
5555 mock_webhook .config .get_value = Mock (return_value = None )
5656 mock_webhook .security_suspicious_paths = DEFAULT_SUSPICIOUS_PATHS
5757 mock_webhook .security_committer_identity_check = True
58+ mock_webhook .security_trusted_committers = []
5859 mock_webhook .parent_committer = "test-user"
5960 mock_webhook .last_committer = "test-user"
6061 return mock_webhook
@@ -214,6 +215,7 @@ def mock_github_webhook(self) -> Mock:
214215 mock_webhook .config .get_value = Mock (return_value = None )
215216 mock_webhook .security_suspicious_paths = DEFAULT_SUSPICIOUS_PATHS
216217 mock_webhook .security_committer_identity_check = True
218+ mock_webhook .security_trusted_committers = []
217219 mock_webhook .parent_committer = "test-user"
218220 mock_webhook .last_committer = "test-user"
219221 return mock_webhook
@@ -349,6 +351,37 @@ async def test_committer_identity_check_disabled(self, runner_handler: RunnerHan
349351 await runner_handler .run_security_committer_identity ()
350352 mock_progress .assert_not_called ()
351353
354+ @pytest .mark .asyncio
355+ async def test_committer_identity_mismatch_trusted (self , runner_handler : RunnerHandler ) -> None :
356+ """Check passes when last committer is in trusted-committers list."""
357+ runner_handler .github_webhook .parent_committer = "legit-user"
358+ runner_handler .github_webhook .last_committer = "pre-commit-ci[bot]"
359+ runner_handler .github_webhook .security_trusted_committers = ["pre-commit-ci[bot]" , "myorg" ]
360+
361+ with patch .object (runner_handler .check_run_handler , "set_check_in_progress" , new = AsyncMock ()):
362+ with patch .object (runner_handler .check_run_handler , "set_check_success" , new = AsyncMock ()) as mock_success :
363+ await runner_handler .run_security_committer_identity ()
364+
365+ mock_success .assert_called_once ()
366+ call_args = mock_success .call_args
367+ assert call_args .kwargs ["name" ] == SECURITY_COMMITTER_IDENTITY_STR
368+ assert "trusted-committers" in call_args .kwargs ["output" ]["summary" ]
369+
370+ @pytest .mark .asyncio
371+ async def test_committer_identity_mismatch_not_trusted (self , runner_handler : RunnerHandler ) -> None :
372+ """Check fails when last committer is NOT in trusted-committers list."""
373+ runner_handler .github_webhook .parent_committer = "legit-user"
374+ runner_handler .github_webhook .last_committer = "suspicious-user"
375+ runner_handler .github_webhook .security_trusted_committers = ["pre-commit-ci[bot]" ]
376+
377+ with patch .object (runner_handler .check_run_handler , "set_check_in_progress" , new = AsyncMock ()):
378+ with patch .object (runner_handler .check_run_handler , "set_check_failure" , new = AsyncMock ()) as mock_failure :
379+ await runner_handler .run_security_committer_identity ()
380+
381+ mock_failure .assert_called_once ()
382+ call_args = mock_failure .call_args
383+ assert "suspicious-user" in call_args .kwargs ["output" ]["summary" ]
384+
352385
353386class TestAutoMergeSecurityOverride :
354387 """Test auto-merge is blocked when PR modifies suspicious paths."""
@@ -367,6 +400,7 @@ def mock_github_webhook(self) -> Mock:
367400 mock_webhook .set_auto_merge_prs = []
368401 mock_webhook .security_suspicious_paths = DEFAULT_SUSPICIOUS_PATHS
369402 mock_webhook .security_committer_identity_check = True
403+ mock_webhook .security_trusted_committers = []
370404 mock_webhook .security_mandatory = True
371405 mock_webhook .last_commit = Mock ()
372406 mock_webhook .ctx = None
@@ -616,6 +650,7 @@ def mock_github_webhook(self) -> Mock:
616650 mock_webhook .custom_check_runs = []
617651 mock_webhook .security_suspicious_paths = DEFAULT_SUSPICIOUS_PATHS
618652 mock_webhook .security_committer_identity_check = True
653+ mock_webhook .security_trusted_committers = []
619654 mock_webhook .security_mandatory = True
620655 mock_webhook .last_commit = Mock ()
621656 mock_webhook .last_commit .sha = "abc123"
@@ -686,6 +721,7 @@ async def test_security_checks_partial_config(
686721 """Only configured security checks are added to required list."""
687722 check_run_handler .github_webhook .security_suspicious_paths = []
688723 check_run_handler .github_webhook .security_committer_identity_check = True
724+ check_run_handler .github_webhook .security_trusted_committers = []
689725
690726 with patch .object (
691727 check_run_handler ,
@@ -712,6 +748,7 @@ def mock_github_webhook(self) -> Mock:
712748 mock_webhook .security_mandatory = True
713749 mock_webhook .security_suspicious_paths = DEFAULT_SUSPICIOUS_PATHS
714750 mock_webhook .security_committer_identity_check = True
751+ mock_webhook .security_trusted_committers = []
715752 mock_webhook .ctx = None
716753 mock_webhook .config = Mock ()
717754 mock_webhook .config .get_value = Mock (return_value = None )
0 commit comments