diff --git a/prowler/providers/github/services/repository/repository_denies_branch_deletion/__init__.py b/prowler/providers/github/services/repository/repository_denies_branch_deletion/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/github/services/repository/repository_denies_branch_deletion/repository_denies_branch_deletion.metadata.json b/prowler/providers/github/services/repository/repository_denies_branch_deletion/repository_denies_branch_deletion.metadata.json new file mode 100644 index 0000000000..142d341017 --- /dev/null +++ b/prowler/providers/github/services/repository/repository_denies_branch_deletion/repository_denies_branch_deletion.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "github", + "CheckID": "repository_denies_branch_deletion", + "CheckTitle": "Check if repository denies branch deletion", + "CheckType": [], + "ServiceName": "repository", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "high", + "ResourceType": "Other", + "Description": "Ensure that the repository denies branch deletion.", + "Risk": "Allowing the deletion of protected branches by users with push access increases the risk of accidental or intentional branch removal, potentially resulting in significant data loss or disruption to the development process.", + "RelatedUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#allow-deletions", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Deny the ability to delete protected branches to ensure the preservation of critical branch data. This prevents accidental or malicious deletions and helps maintain the integrity and stability of the repository.", + "Url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/github/services/repository/repository_denies_branch_deletion/repository_denies_branch_deletion.py b/prowler/providers/github/services/repository/repository_denies_branch_deletion/repository_denies_branch_deletion.py new file mode 100644 index 0000000000..3cd9561f14 --- /dev/null +++ b/prowler/providers/github/services/repository/repository_denies_branch_deletion/repository_denies_branch_deletion.py @@ -0,0 +1,44 @@ +from typing import List + +from prowler.lib.check.models import Check, Check_Report_Github +from prowler.providers.github.services.repository.repository_client import ( + repository_client, +) + + +class repository_denies_branch_deletion(Check): + """Check if a repository denies branch deletion + + This class verifies whether each repository denies branch deletion. + """ + + def execute(self) -> List[Check_Report_Github]: + """Execute the Github Repository Denies Branch Deletion check + + Iterates over all repositories and checks if they deny branch deletion. + + Returns: + List[Check_Report_Github]: A list of reports for each repository + """ + findings = [] + for repo in repository_client.repositories.values(): + report = Check_Report_Github(self.metadata()) + report.resource_id = repo.id + report.resource_name = repo.name + report.status = "FAIL" + report.status_extended = ( + f"Repository {repo.name} does allow branch deletion." + ) + + if ( + repo.default_branch_protection + and not repo.default_branch_protection.allow_branch_deletion + ): + report.status = "PASS" + report.status_extended = ( + f"Repository {repo.name} does deny branch deletion." + ) + + findings.append(report) + + return findings diff --git a/prowler/providers/github/services/repository/repository_service.py b/prowler/providers/github/services/repository/repository_service.py index 2426b7f456..73b7d7e534 100644 --- a/prowler/providers/github/services/repository/repository_service.py +++ b/prowler/providers/github/services/repository/repository_service.py @@ -48,12 +48,16 @@ class Repository(GithubService): protection.required_linear_history ) allow_force_pushes = protection.allow_force_pushes + branch_deletion = protection.allow_deletions + branch_protection = Protection( require_pull_request=require_pr, approval_count=approval_cnt, linear_history=required_linear_history, allow_force_push=allow_force_pushes, + allow_branch_deletion=branch_deletion, ) + except Exception as e: logger.warning( f"Could not get branch protection for repo {repo.name}: {e}" @@ -82,7 +86,8 @@ class Protection(BaseModel): require_pull_request: bool = False approval_count: int = 0 linear_history: bool = False - allow_force_push: bool = False + allow_force_push: bool = True + allow_branch_deletion: bool = True class Repo(BaseModel):