Enforce governance with GitHub controls
Once those boundaries are in place, the next step is making sure they're consistently applied. It isn't enough to define rules—those decisions need to be enforced in a way that can't be bypassed. GitHub provides the controls to turn governance into something concrete, so every action is validated and aligned with your policies.
In this unit, you'll learn:
- What enforcement controls are and how they apply in GitHub
- How to enforce policies using rulesets, checks, and environments
- How to route ownership using CODEOWNERS
- How to implement guardrails and layered enforcement
What are enforcement controls?
- Rulesets / branch protection
- Required checks
- CODEOWNERS
- Environments
- Guardrail workflows
How enforcement works in GitHub
GitHub enforces governance by applying rules and controls directly within the development workflow. These controls ensure that agent actions are validated, reviewed, and blocked when they don't meet defined policies.
Apply rulesets and branch protection
For protected branches such as main, enforce:
- PR required to merge
- required checks must pass
- required approving reviews (per risk)
- require CODEOWNERS review (for sensitive paths)
- restrict direct pushes
- block force pushes and branch deletion
Example: PR checks trigger
on:
pull_request:
branches: [main]
Use required checks as validation
Required checks should map to your governance goals:
- build and unit tests (quality)
- security scans (risk)
- policy checks (for workflows/infra changes)
Decision guidance: Treat renaming or removing required checks as high risk. If checks drift, governance drifts
Route ownership using CODEOWNERS
/security/ @security-team
/infra/ @platform-team
/.github/workflows/ @platform-team
* @core-team
Decision guidance: Make sure "require CODEOWNERS review" is enabled, or CODEOWNERS becomes advisory only.
Gate deployments with environments
Use environments to:
- require reviewers for production deploys
- restrict production secrets to production environment only
- maintain a clear deployment and approval record
Decision guidance: If a workflow accesses production secrets, treat it as critical risk and gate it.
Enforceable guardrails for local agent execution (Copilot CLI hooks)
If your organization uses repository-scoped configuration for local agents, enforce deny rules that block dangerous commands before execution.
This turns policy into a technical control, reducing the risk of unintended or destructive actions.
Example: Copilot CLI preToolUse hook that blocks high-risk commands
{
"hook": "preToolUse",
"tools": ["shell(bash)"],
"rules": [
{ "match": "sudo", "permissionDecision": "deny" },
{ "match": "rm -rf /", "permissionDecision": "deny" },
{ "match": "curl .*\\|\\s*bash", "permissionDecision": "deny" }
]
}
Decision guidance: Use enforceable hooks for blocking. Logging and banners are helpful, but they don't prevent execution.
Add defense-in-depth workflows
Some organizations add a guardrail check to ensure that:
- Agent-authored PRs can't merge automatically
- Approvals are counted only from human users, not bots
- Review requirements can't be satisfied by automation identities
Example: Guardrail workflow that blocks Copilot-authored PRs and requires human approval
name: agent-guardrails
on:
pull_request:
branches: ["main"]
permissions:
contents: read
jobs:
enforce-human-review:
runs-on: ubuntu-latest
steps:
- name: Fail if PR is authored by Copilot agent
if: ${{ github.event.pull_request.user.login == 'github-copilot[bot]' }}
run: |
echo "PRs authored by github-copilot[bot] must be opened/owned by a human."
exit 1
- name: Require at least one human approval
uses: actions/github-script@v7
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const pull_number = context.payload.pull_request.number;
const reviews = await github.rest.pulls.listReviews({ owner, repo, pull_number });
const approvedByHuman = reviews.data.some(r =>
r.state === "APPROVED" &&
r.user &&
r.user.type === "User" &&
r.user.login !== "github-copilot[bot]"
);
if (!approvedByHuman) {
core.setFailed("Human approval is required before merge.");
}
Decision guidance: This is defense in depth. You still want branch protections and CODEOWNERS, but guardrail workflows can enforce rules that aren't expressible via settings alone.
Apply layered enforcement model
Governance should operate across multiple layers:
- pre-action constraints (permissions)
- in-action validation (checks)
- post-action traceability (logs, artifacts)
If a control isn't enforced by the platform, it should be treated as optional.
Why enforcement must be automated
Agents operate at scale and speed. Governance that relies on human behavior alone will fail under these conditions. Enforcement must be built into the system so unsafe actions are blocked before they occur.
Important
"Controls in docs only" is an anti-pattern. If the platform can't enforce it, it will be bypassed.
Key takeaway
Governance in GitHub is enforced through policy, not trust. By combining rulesets, checks, ownership, and environment gates, you ensure that every action is validated and can't bypass defined controls—making agent behavior consistent, auditable, and safe at scale.
Enforcement controls block unsafe actions, but high-risk decisions still require human judgment. Next, you'll design human-in-the-loop workflows.