From a212916a49b596208d08a9da27c57020dc1d0ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=90=B4=E7=84=9A=E9=9F=B3=E8=90=BD?= <99181324+qinfenyinluo@users.noreply.github.com> Date: Wed, 1 Jul 2026 18:29:13 +0800 Subject: [PATCH] fix(github): skip archived repos in CODEOWNERS check (#11735) Co-authored-by: Daniel Barranquero --- prowler/CHANGELOG.md | 1 + .../repository_has_codeowners_file.py | 3 ++ .../repository_has_codeowners_file_test.py | 52 +++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 420b7e7654..2188797585 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -32,6 +32,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### 🐞 Fixed +- GitHub `repository_has_codeowners_file` check no longer flags archived repositories, since they are read-only and cannot be updated without first being unarchived, making the finding not actionable [(#11735)](https://github.com/prowler-cloud/prowler/pull/11735) - Report secret-scanning checks as `MANUAL` instead of `PASS` when the scanner fails (non-zero exit, timeout, unparseable output or missing binary), so a scanner failure is no longer indistinguishable from "no secrets found" [(#11694)](https://github.com/prowler-cloud/prowler/pull/11694) - Avoid a false `FAIL` in `cloudwatch_log_group_no_secrets_in_logs` when a multiline event's secrets are all removed by `secrets_ignore_patterns` during the rescan [(#11694)](https://github.com/prowler-cloud/prowler/pull/11694) - Key the `cloudwatch_log_group_no_secrets_in_logs` secret scan by log group ARN instead of name, so same-named log groups and streams in different regions no longer collide and reuse each other's findings [(#11694)](https://github.com/prowler-cloud/prowler/pull/11694) diff --git a/prowler/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file.py b/prowler/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file.py index 7120e0411a..2ece6abf42 100644 --- a/prowler/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file.py +++ b/prowler/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file.py @@ -22,6 +22,9 @@ class repository_has_codeowners_file(Check): """ findings = [] for repo in repository_client.repositories.values(): + if repo.archived: + continue + if repo.codeowners_exists is not None: report = CheckReportGithub(metadata=self.metadata(), resource=repo) if repo.codeowners_exists: diff --git a/tests/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file_test.py b/tests/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file_test.py index a181ec8404..d56aed307e 100644 --- a/tests/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file_test.py +++ b/tests/providers/github/services/repository/repository_has_codeowners_file/repository_has_codeowners_file_test.py @@ -145,3 +145,55 @@ class Test_repository_has_codeowners_file: result[0].status_extended == f"Repository {repo_name} does have a CODEOWNERS file." ) + + def test_archived_repository_no_codeowners_is_skipped(self): + repository_client = mock.MagicMock + repo_name = "archived-repo" + repository_client.repositories = { + 3: Repo( + id=3, + name=repo_name, + owner="account-name", + full_name="account-name/archived-repo", + default_branch=Branch( + name="main", + protected=False, + default_branch=True, + require_pull_request=False, + approval_count=0, + required_linear_history=False, + allow_force_pushes=True, + branch_deletion=True, + status_checks=False, + enforce_admins=False, + require_code_owner_reviews=False, + require_signed_commits=False, + conversation_resolution=False, + ), + private=False, + securitymd=True, + codeowners_exists=False, + secret_scanning_enabled=False, + archived=True, + pushed_at=datetime.now(timezone.utc), + delete_branch_on_merge=False, + ), + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_github_provider(), + ), + mock.patch( + "prowler.providers.github.services.repository.repository_has_codeowners_file.repository_has_codeowners_file.repository_client", + new=repository_client, + ), + ): + from prowler.providers.github.services.repository.repository_has_codeowners_file.repository_has_codeowners_file import ( + repository_has_codeowners_file, + ) + + check = repository_has_codeowners_file() + result = check.execute() + assert len(result) == 0