Back to Checks
github

Repository grants workflows a read-only default GITHUB_TOKEN

repository_default_workflow_permissions_read_only
Service: repositorySeverity: high
OfficialBuilt-inVerified
Categories:ci-cdsoftware-supply-chain
Resource Type:NotDefined

GitHub Actions repository settings define the default GITHUB_TOKEN permissions granted to every workflow run in the repository.

The evaluation determines whether the repository default is read-only, so that workflows have to opt in to write access through an explicit permissions block.

Risk

A write-capable default GITHUB_TOKEN is available to every workflow in the repository, so any compromised step or dependency inherits it, leading to:

  • Code integrity loss from pushed commits, moved tags, or altered releases
  • Supply chain compromise when the token publishes packages or artifacts
  • Weakened review controls when the token acts on pull requests and issues

Run this check with Prowler

Run in Prowler Cloud
Run
prowler github --checks repository_default_workflow_permissions_read_only

Recommendation

Set the repository default GITHUB_TOKEN permissions to read-only and grant write scopes per workflow with an explicit permissions block, following least privilege.

A repository can override an organization default, so verify this setting per repository even when the organization already defaults to read-only. Prefer short-lived GitHub App tokens over broad credentials when a workflow genuinely needs write access.

Remediation

CLI

gh api --method PUT /repos/<owner>/<repository>/actions/permissions/workflow -f default_workflow_permissions=read

Other

1Sign in to GitHub as a repository administrator
2Go to the repository > Settings
3In the left sidebar, click Actions > General
4Under Workflow permissions, select Read repository contents and packages permissions
5Click Save

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_workflow_permissions_read_only(Check):
    """Ensure repositories grant workflows a read-only default GITHUB_TOKEN.

    A read-only default forces workflows to request write access explicitly, instead of
    every workflow run starting with a token that can write to the repository.
    """

    def execute(self) -> List[CheckReportGithub]:
        """Run the default workflow permissions verification for each discovered repository.

        Returns:
            List[CheckReportGithub]: Collection of check reports describing the default GITHUB_TOKEN permissions.
        """
        findings: List[CheckReportGithub] = []
        for repo in repository_client.repositories.values():
            if repo.default_workflow_permissions is None:
                continue

            report = CheckReportGithub(metadata=self.metadata(), resource=repo)

            if repo.default_workflow_permissions == "read":
                report.status = "PASS"
                report.status_extended = f"Repository {repo.name} grants workflows a read-only default GITHUB_TOKEN."
            else:
                report.status = "FAIL"
                report.status_extended = f"Repository {repo.name} grants workflows a default GITHUB_TOKEN with {repo.default_workflow_permissions} permissions."

            findings.append(report)

        return findings