Back to Checks
github

Repository default branch denies force pushes

repository_default_branch_disallows_force_push
Service: repositorySeverity: high
OfficialBuilt-inVerified
Categories:software-supply-chain
Resource Type:NotDefined

GitHub repository default branch blocks force pushes through branch protection.

Evaluates whether the default branch permits force pushes. This protection can be enforced through classic branch protection or repository rulesets.

Risk

Allowing force pushes on the default branch erodes integrity and auditability by enabling history rewrites and deletion of commits. Attackers or insiders can inject unreviewed code, bypass reviews and status checks, and corrupt PRs, risking supply-chain compromise and reduced availability.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler github --checks repository_default_branch_disallows_force_push

Recommendation

Disable Allow force pushes on the default branch. Enforce PR-based changes with required reviews and status checks, require signed commits and linear history, and restrict bypass to minimal actors. Apply protections to admins too to uphold least privilege and defense in depth.

Remediation

Terraform

resource "github_branch_protection_v3" "<example_resource_name>" {
  repository_id       = "<example_resource_id>"
  pattern             = "<default_branch_name>"

  allows_force_pushes = false # Critical: disallows force pushes on the default branch
}

Other

1In GitHub, open the repository and go to Settings
2In the sidebar, click Branches
3Edit the protection rule for the default branch (or Add rule with the default branch name)
4Ensure Allow force pushes is unchecked/disabled
5Click Save changes

Check Code

from typing import List

from prowler.lib.check.models import Check, CheckReportGithub
from prowler.providers.github.services.repository.repository_client import (
    repository_client,
)


class repository_default_branch_disallows_force_push(Check):
    """Check if a repository denies force push

    This class verifies whether each repository denies force push.
    """

    def execute(self) -> List[CheckReportGithub]:
        """Execute the Github Repository Denies Force Push check

        Iterates over all repositories and checks if they deny force push.

        Returns:
            List[CheckReportGithub]: A list of reports for each repository
        """
        findings = []
        for repo in repository_client.repositories.values():
            if repo.default_branch.allow_force_pushes is not None:
                report = CheckReportGithub(metadata=self.metadata(), resource=repo)
                report.status = "FAIL"
                report.status_extended = f"Repository {repo.name} does allow force pushes on default branch ({repo.default_branch.name})."
                if (
                    repo.default_branch.allow_force_pushes_source
                    == "ruleset_not_active"
                ):
                    report.status_extended = f"Repository {repo.name} has force pushes disallowed in a ruleset on default branch ({repo.default_branch.name}), but the ruleset is not active."

                if not repo.default_branch.allow_force_pushes:
                    report.status = "PASS"
                    report.status_extended = f"Repository {repo.name} does deny force pushes on default branch ({repo.default_branch.name})."

                findings.append(report)

        return findings