Repository grants workflows a read-only default GITHUB_TOKEN
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 Cloudprowler github --checks repository_default_workflow_permissions_read_onlyRecommendation
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=readOther
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 findingsReferences
- https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#setting-the-permissions-of-the-github_token-for-your-repository
- https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication
- https://docs.github.com/en/rest/actions/permissions