Step 2

Exercise 1: Policy Guardrails

On this page

Exercise 1: Policy Guardrails (~10 min)

Goal: Learn to SELECT the right rules for your context — then prove that policy blocks merges before any scan runs.

🎯 “Don’t rely on heroics. Encode guardrails into the workflow.” Ask yourself: “What if the senior security reviewer is on vacation?”

📝 Open docs/rule-selection-guide.md — use the decision framework to classify your repository and select rules.


Step 1: Classify Your Repository and Select Rules (~3 min)

Before configuring anything, DECIDE which rules to apply. GitHub rulesets offer 15+ available rules — choosing the right ones depends on your context.

1a. Classify the workshop repository:

Factor Your Answer
Repository type 🔴 Production / 🟡 Staging / 🟢 Experimental / 🔵 Library
Regulatory requirements? Yes (financial/healthcare/govt) / No
Team size Solo / Small (2-5) / Large (5+)
CI/CD maturity None / Basic (tests) / Full (tests + scanning + deploy)

For this workshop, classify as 🔴 Production (regulated enterprise scenario).

1b. Review the full rule menu and select rules for your classification. Key rules to consider:

Rule Purpose Mitigates Threat Select?
Require PR before merging No direct commits Row 6, 7
Require 2+ approvals Multi-reviewer gate Row 6
Dismiss stale reviews Re-review after changes Row 7
Require status checks (CodeQL) Automated vulnerability check Row 2
Block force pushes Prevent history rewriting Row 7
Require signed commits Identity verification Row 6 Consider
Require linear history Clean audit trail Row 7 Consider
Require conversation resolution All review comments addressed Row 8, 9

[!TIP] Each rule traces back to a threat model row. This is NOT a checklist to blindly enable everything — it’s a decision framework. For experimental repos, you’d select fewer rules. For production, more.


Step 2: Create an Org-Level Ruleset (~4 min)

2a. Navigate to Organization Rulesets

  • Go to your Organization SettingsRepositoriesRulesets
  • Click New rulesetNew branch ruleset

2b. Configure Ruleset Metadata

Setting Value
Name production-security-guardrails
Enforcement Active
Target repositories Dynamic list by name → *-demo
Target branches Default branch

2c. Enable Rules Based on Your Selection

Enable the rules you selected in Step 1. For the 🔴 Production classification:

  • Require a pull request before merging
    • Required approvals: 1 (for this workshop; in production, use 2+)
    • Dismiss stale reviews when new commits are pushed: ✅
  • Require status checks to pass
    • Add required check: CodeQL
  • Block force pushes
  • Require conversation resolution before merging (ensures review comments are addressed)

For a TIERED strategy, you would create additional rulesets:

  • staging-standard → Target: staging-* → 1 approval, CodeQL only
  • experimental-minimal → Target: experimental-* → 1 approval, no status checks

Click Create to save the ruleset.


Step 3: Test the Policy (~3 min)

# Create a trivial change
echo "// policy test" >> README.md
git add README.md
git commit -m "Test policy guardrails"
git push origin workshop/secure-by-design
  • Open a Pull Request from workshop/secure-by-designmain
  • Observe: The merge button is blocked — status checks must pass AND approvals are required
  • Attempt to merge without passing checks → ❌ Blocked
  • Once checks pass and approvals are given → ✅ Merge allowed

Verify the merge was blocked until ALL conditions were met:

  • ✅ Required number of approvals received
  • ✅ CodeQL status check passed
  • ✅ No force push attempted
  • ✅ Conversations resolved (if enabled)

Key Insight

Security policy means a PR cannot merge even if every human involved agrees — if the automated checks fail, the merge is blocked. That’s stronger than any code review. A human can be persuaded; a policy check cannot.

The decision framework ensures rules are JUSTIFIED, not arbitrary. Each rule traces to a threat model row. A production repo needs strict rules; an experimental repo needs fewer. One size does NOT fit all.

[!TIP] Run scripts/verify-exercise1.sh to validate your Exercise 1 completion.

to navigate between steps