For the complete documentation index, see llms.txt. This page is also available as Markdown.

GH_PUSH_TO_DEFAULT

Summary

Forestall ACL Alias

GH_PUSH_TO_DEFAULT

Edge Type

Attack Path

Affected Object Types

GitHub Repositories

Exploitation Certainty

Certain

GitHub Role / Permission

Repository write (push) or maintain, on an unprotected default branch

Description

GH_PUSH_TO_DEFAULT represents that a user or team can push code directly to a repository's default branch. The default branch is what CI/CD builds and deploys from, so the ability to write to it without review is a supply-chain foothold.

The edge is created only when both conditions hold:

  • The entity has write-level permission (push or maintain) on the repository, and

  • The default branch is not protected — there is no branch protection rule gating direct pushes. This is the relational form of the FS6021 (No Branch Protection) finding.

Admin holders are intentionally not given this edge: they are already modelled by GH_ADMIN (full control, which also includes the ability to remove protection and push). Archived repositories cannot be pushed to and are excluded.

When the default branch is protected (required reviews, status checks, or push restrictions), a direct push is blocked and this edge is not created — the writer must go through a reviewed pull request instead.

Identification

GitHub Web Interface

  1. Open the repository → Settings → Branches. If the default branch has no protection rule, direct pushes are allowed.

  2. Open Settings → Collaborators and teams. Any user or team with Write or Maintain can push directly to the unprotected default branch.

GitHub CLI

Check whether the default branch is protected (404 = unprotected):

List teams and collaborators that hold write-level access:

Exploitation

When the default branch is unprotected, a write-level entity can compromise the repository's build and deployment pipeline with a single push:

  1. Inject a malicious GitHub Actions workflow. A workflow pushed to .github/workflows/ runs with the repository's secrets and GITHUB_TOKEN. Where OIDC federation is configured, it can mint a cloud token and pivot out of GitHub entirely.

  2. Tamper with shipped code. Backdoor application source on the default branch so the next deploy carries the attacker's payload to production.

  3. Exfiltrate secrets at build time. Print or transmit repository/environment secrets from a workflow step.

Because no review gates the push, the change reaches the default branch (and the pipeline) immediately — hence Certain certainty.

Mitigation

  1. Protect the default branch. Enable a branch protection rule (or a ruleset) on the default branch: require pull requests, require at least one review, and disallow direct pushes. This removes the edge entirely. See FS6021.

  2. Require review for workflow changes. Use CODEOWNERS to require an owner's review for .github/workflows/ so workflow tampering cannot be self-merged.

  3. Grant least privilege. Prefer triage/read over write where contributors do not need to push. Manage write access through teams, not direct collaborator grants.

  4. Constrain Actions and OIDC. Set default workflow permissions to read-only, restrict which actions can run, and scope cloud federated-identity credentials (subject claim) to specific protected branches/environments rather than the whole repository.

  5. Include administrators in protection. Enable "Do not allow bypassing the above settings" so even admins cannot push directly to the default branch on sensitive repositories.

Detection

Monitor the GitHub audit log and Git events for direct writes to the default branch:

Event
Description

git.push

A push was received (correlate ref = default branch, no associated PR)

protected_branch.destroy

A branch protection rule was removed (opens this edge)

repo.update_member / team.add_repository

Write-level access was granted

workflows run from an unexpected actor

A new/modified workflow executed shortly after a direct push

Alert on direct pushes to the default branch that are not associated with a reviewed pull request, on any removal of branch protection, and on workflow runs that request id-token: write from an unexpected actor.

References

Last updated

Was this helpful?