Checkpoint Lab — Secret Scanning, Push Protection, Custom Patterns, Bypass Controls, and Incident Response
The checkpoint integrates prevention, a fake leak fixture, revocation-first response, location scoping, bypass review, and history-rewrite decision-making. You will prove that a GitHub-documented dummy secret is blocked, run a simulated incident record through containment and remediation, and produce a production-ready leak/bypass runbook before moving to provenance in Chapter 25.
Learning objectives
- Predict and verify the repository/security state changes caused by enabling protection and attempting a blocked write.
- Run a harmless leak simulation using a GitHub-published dummy secret without creating an authentic credential.
- Execute a revocation-first simulated incident record, including non-Git location scope and dependent-system migration.
- Write a bypass-review policy and a history-rewrite decision record with plan-dependent alternatives.
- Produce a verification checklist that proves no live credential remains and closes the chapter with a production operating model.
1. Scenario and two predictions before changing state
You are the release engineer for a fictional service called Atlas Relay. A previous retrospective found that developers occasionally pasted credentials into configuration examples. You must prove prevention works, then demonstrate how the team would respond if a credential had already escaped into both Git and an issue comment.
| Prediction | Expected state after action | How you will verify independently |
|---|---|---|
| P1: enabling repository push protection changes hosted security configuration, not Git history | Security settings change; default branch SHA stays the same |
REST security_and_analysis + GitHub commit SHA
before/after
|
| P2: attempting to save the documented dummy secret is blocked and canceled | No commit/file and no bypass alert is created | UI block + contents API 404/absence + unchanged branch SHA + hidden-secret alert list |
| P3: simulated revocation changes incident state before any cleanup decision | Fixture moves active-simulated → revoked-simulated | Versioned incident JSON/diff, with no credential value present |
Write your predictions into CHECKPOINT.md before the
experiment. Prediction turns a lab from a click sequence into a
causal test.
2. Setup and baseline evidence
OWNER=$(gh api -H "X-GitHub-Api-Version: 2026-03-10" user --jq .login)
REPO="$OWNER/gh-secret-incident-checkpoint"
gh repo create "$REPO" --public --add-readme --description "Disposable Chapter 24 checkpoint"
DEFAULT_BRANCH=$(gh repo view "$REPO" --json defaultBranchRef --jq .defaultBranchRef.name)
BASE_SHA=$(gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO/commits/$DEFAULT_BRANCH" --jq .sha)
gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO" \
--jq '{id,full_name,visibility,default_branch,security_and_analysis}'
printf 'Baseline SHA: %s\n' "$BASE_SHA"
In the web UI, inspect account-level Push protection for yourself. Then inspect repository Settings → Advanced Security. Record what is already enabled before changing it. Public repositories can use Secret Protection features free; if the current UI already reports them enabled, do not toggle them off merely to create a before-state.
3. Enable/confirm repository Secret Protection and prove Git did not change
Enable Secret Protection and repository push protection if necessary. This is a security-setting mutation, so record who performed it and why. Re-read the repository object and compare the branch SHA to the baseline.
AFTER_SETTINGS_SHA=$(gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO/commits/$DEFAULT_BRANCH" --jq .sha)
gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO" \
--jq '.security_and_analysis'
printf 'baseline=%s after-settings=%s\n' "$BASE_SHA" "$AFTER_SETTINGS_SHA"
test "$BASE_SHA" = "$AFTER_SETTINGS_SHA" && echo "Prediction P1 confirmed: settings changed without a Git commit."
4. Leak-prevention test: the fake secret is blocked before persistence
Use the current GitHub web editor to create
training/checkpoint-secret.txt. Paste only the official
GitHub dummy value below, attempt to commit, observe the
push-protection message, then cancel and discard.
Do not bypass.
secret_scanning_EXAMPLE_DUMMY_TOKEN_NOT_REAL_12345
Capture the pattern/display name and blocked file/line from the UI as non-sensitive evidence. Do not screenshot or copy real repository secrets in production incidents. Then prove nothing was stored:
CURRENT_SHA=$(gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO/commits/$DEFAULT_BRANCH" --jq .sha)
printf 'after-block=%s\n' "$CURRENT_SHA"
if gh api -H "X-GitHub-Api-Version: 2026-03-10" \
"repos/$REPO/contents/training/checkpoint-secret.txt" >/dev/null 2>&1; then
echo "Unexpected: file exists; stop and inspect before proceeding."
exit 1
else
echo "Expected: blocked/canceled file does not exist."
fi
gh api --paginate -H "X-GitHub-Api-Version: 2026-03-10" \
"repos/$REPO/secret-scanning/alerts?hide_secret=true&per_page=100" \
--jq '.[] | {number,state,secret_type,validity,resolution,push_protection_bypassed}'
P2 is satisfied when the write was blocked, the candidate file is absent, the branch SHA is unchanged, and no bypass alert was created by this canceled attempt. If you see unexpected state, stop and interpret it before continuing.
5. Simulate the incident that prevention failed to stop
Now create a redacted incident record. The fixture represents an already-exposed fictional credential but stores no secret. Commit this record because incident evidence belongs in a durable controlled channel; in a real organization that channel may be an incident-management system rather than the public repository.
mkdir -p training
cat > training/incident.json <<'JSON'
{
"incident": "INC-CH24-CHECKPOINT",
"credential": "fictional_atlas_deployer",
"secret_value": "<redacted-never-recorded>",
"issuer_status": "active-simulated",
"exposure_window": "2026-08-19T17:00:00Z/2026-08-19T17:12:00Z",
"locations": [
"git-commit:SIMULATED_SHA:config/deploy.example:4",
"issue-comment:SIMULATED_ISSUE_17_COMMENT_2"
],
"consumers": ["staging-deploy", "release-bot"],
"provider_audit": "pending-simulated",
"history_rewrite": "undecided"
}
JSON
git clone "https://github.com/$REPO.git" ch24-checkpoint
cd ch24-checkpoint
mkdir -p training
cp ../training/incident.json training/incident.json
git add training/incident.json
git commit -m "Add redacted Chapter 24 incident fixture"
git push origin HEAD
<redacted-never-recorded>. Never commit a real
incident’s credential value to an incident record.
6. Execute the runbook: revocation before remediation
Before editing the simulated Git/issue locations, update the fixture to show provider containment. This models the sequencing decision. In a real incident, a credential owner/provider administrator would perform the actual revoke/rotate operation in the issuing service, not through GitHub secret scanning.
import json
from pathlib import Path
p = Path("training/incident.json")
data = json.loads(p.read_text())
data["issuer_status"] = "revoked-simulated"
data["provider_audit"] = "no-unauthorized-use-found-simulated"
data["consumers_migrated"] = {
"staging-deploy": True,
"release-bot": True
}
p.write_text(json.dumps(data, indent=2) + "\n")
print("Revocation simulation recorded before content cleanup.")
git add training/incident.json
git commit -m "Record simulated revocation and consumer migration"
git push origin HEAD
git log --oneline -3
Verify two directions: the old credential would be rejected
(revoked-simulated) and both legitimate consumers are
marked migrated. A real runbook must obtain independent evidence
from the issuer/application rather than trusting the incident note
alone.
7. Scope all locations, including non-Git surfaces
The fixture names a Git location and an issue comment. In a live secret-scanning alert, the locations endpoint can enumerate commit, wiki, issue, Discussion, PR and review locations. Use this shape in the runbook, but do not invent a real alert number for the checkpoint.
# TEMPLATE — run only when you have a real alert number and authorization.
ALERT_NUMBER=123
# gh api -H "X-GitHub-Api-Version: 2026-03-10" \
# "repos/$REPO/secret-scanning/alerts/$ALERT_NUMBER/locations?per_page=100" \
# --paginate --jq '.[] | {type,details}'
echo "Checkpoint uses synthetic locations; no real alert mutation is required."
For each location, record whether the credential value is still visible, who can access the surface, and how it will be removed/replaced. Because the credential is already revoked in the runbook sequence, this step reduces residual disclosure/reuse risk instead of pretending to contain authentication.
8. Write the history-rewrite decision
Add a decision to the incident file or runbook. For this fictional
revocable deployment credential, choose
not-required after revocation unless another
policy/compliance reason exists. Explain that GitHub history
rewriting changes commit hashes, may break signatures/PR diffs,
requires collaborator/fork coordination, and cannot erase copies
outside repository control.
import json
from pathlib import Path
p = Path("training/incident.json")
data = json.loads(p.read_text())
data["history_rewrite"] = {
"decision": "not-required",
"reason": "Credential is revocable and is simulated revoked; no non-revocable sensitive data is present.",
"reconsider_if": [
"regulated or non-revocable data is discovered",
"legal/compliance policy requires purge",
"additional sensitive content remains beyond credential value"
]
}
p.write_text(json.dumps(data, indent=2) + "\n")
git-filter-repo or a force/mirror
push in this checkpoint.
If a real incident requires history rewriting, use GitHub’s current
sensitive-data removal procedure, freeze/coordinate repository
writes, plan for changed SHAs/signatures/PRs/clones/forks, and
obtain the required approvals/support.
9. Produce a deployment-quality bypass/exception policy
Your runbook must define bypass authority even though the mandatory personal repository does not require delegated bypass. Use a plan-dependent alternative: self-bypass with durable reason in simple public repositories; delegated bypass with independent reviewers in eligible Team organization repositories; exemptions only for trusted automation when redesign is impractical.
| Policy field | Checkpoint requirement |
|---|---|
| Default | Remove the detected value; no bypass for real credentials. |
| Allowed reasons | False positive or demonstrably non-secret test data; “fix later” requires incident owner and immediate containment plan. |
| Requester evidence | Pattern, path, why safe, owner, expiry/cleanup ticket. |
| Approver | Independent security/repository owner where delegated bypass is available. |
| Expiry | Exception/bypass request must be time-bounded; current delegated requests expire after seven days. |
| Exemptions | Rare, actor-specific, reviewed periodically, never granted to ordinary developers for convenience. |
| Metrics | Bypass count by pattern/repo/actor/reason and repeat offenders/patterns. |
10. Verification checklist and cleanup/rollback
- The live GitHub dummy token was blocked and never persisted; no real credential was generated or copied.
- Repository security state and branch SHA were recorded before/after enabling protection.
-
Alert inspection used
hide_secret=true; no literal secret was printed to logs/transcripts. - The incident fixture records revocation before content cleanup, provider-use assessment, and consumer migration.
- Both Git and non-Git exposure locations are represented in the incident scope.
- History rewrite has an explicit decision/rationale and was not executed in the lab.
- The bypass policy states requester evidence, reviewer authority, expiry, exemptions, and metrics.
git status --short
git log --oneline -5
git show HEAD:training/incident.json
gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO" \
--jq '{full_name,visibility,archived,security_and_analysis}'
gh api --paginate -H "X-GitHub-Api-Version: 2026-03-10" \
"repos/$REPO/secret-scanning/alerts?hide_secret=true&per_page=100" \
--jq '.[] | {number,state,secret_type,validity,resolution,push_protection_bypassed}'
cd ..
# Reversible end-state: archive rather than deleting security evidence.
gh repo archive "$REPO" --yes
If you created an optional custom pattern or delegated-bypass configuration in an eligible disposable organization, remove that training-only policy after preserving its dry-run/review evidence. Do not disable organization protections that pre-existed the lab.
Knowledge check
The push-protection dialog appears before the commit is saved. What repository state should you predict if you cancel?
No new commit/file from that attempt. Verify with the branch SHA and contents API rather than assuming the UI canceled correctly.
Why does the checkpoint change
issuer_status before deleting simulated
locations?
It models the security-critical sequence: revoke/rotate first so copied credentials stop working; content cleanup is secondary.
A secret-scanning alert appears only in an issue comment. Is a Git history rewrite useful for that location?
No. Remediate the issue/comment surface and revoke/rotate the credential. Rewriting Git history does not remove an issue comment.
When should a revoked API token still trigger a history rewrite?
Only when additional security/compliance value justifies the disruption—for example regulated/non-revocable sensitive content or explicit purge requirements.
Why is “all writers may always bypass” weaker than delegated bypass?
It collapses write authority and exception approval. Independent delegated review reduces routine self-approval and makes exceptions more auditable.
What proves the incident is actually recovered?
The old credential is unusable, legitimate consumers work with replacement credentials, suspicious-use assessment is complete, exposure locations are handled, and prevention/bypass controls have been verified.
11. Production operating model and Chapter 25 bridge
Chapter 24 adds a credential-leak control plane to the GitHub operating model: free/public historical detection, push-time prevention, provider/generic/custom pattern strategy, safe alert inspection, bypass governance, non-Git location scope, revocation-first containment, consumer migration, and an explicit history-rewrite decision. The durable rule is that a credential’s ability to authenticate is more important than the aesthetic cleanliness of repository history.
Chapter 25 changes the trust question from “did a credential leak?” to “can a consumer verify where an artifact came from and what build produced it?” You will carry forward the same evidence-first discipline into artifact attestations, SBOMs, build provenance, verification, and SLSA-oriented workflows.
Official references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.