fix(leak-guard): config-pattern (public IP) check now blocks + self-test #24

Merged
clawdie merged 1 commit from fix/leak-guard-public-ip-block into main 2026-06-30 06:34:43 +02:00
Owner

Follow-up to #23. The guard's tailnet-IP and MagicDNS paths worked, but the configurable public-IP / domain path silently did not block — proven before the fix and after.

The bug

leak-guard.sh Check 3 ran load_config_patterns | while …; done. In POSIX sh the right side of a pipe is a subshell, so HAS_LEAK=1 set there was lost: a public IP from leak-patterns.conf (e.g. the OSA endpoint that started this whole thread) was printed but exited 0. Checks 1–2 avoided it by using a here-doc, not a pipe.

Fix: read the config into a variable and iterate in the main shell.

Also in this PR

  • Implement LEAK_GUARD_SKIP=1 — the BLOCKED message advertised it; the script never checked it. Now it does.
  • LEAK_PATTERNS_FILE override so the config path is testable.
  • Exclude the guard's own files from scanning (leak-patterns.conf, leak-guard-selftest.sh) — they hold detection patterns by design, so the guard would otherwise flag itself. Folded into a SCAN_EXCLUDES alongside the existing .forgejo/ skip.
  • scripts/leak-guard-selftest.sh — asserts all six paths incl. the public-IP regression, wired as a CI step before the diff scan. Fixtures use RFC5737 / CGNAT / a zeroed tailnet name, so the test file leaks nothing real.
  • Remove the inert __probe_test__.md (placeholders + a "should block" comment but no real value — tested nothing) and the dead check_pattern().

Verified locally

  • self-test: 6/6 pass (incl. public IP from config blocks)
  • guard scanning this branch's own diff: clean (no self-flag)
  • guard in --cached mode blocks a staged tailnet IP (exit 1)

Not in scope (wiring, needs the boxes)

  • Confirm the freebsd runner actually serves layered-soul — no leak-guard runs are recorded, and that runner was offline. Until a run goes green, don't make it a required check.
  • The pre-commit hook only activates per clone (git config core.hooksPath .githooks, or symlink). Worth a setup note/script so it isn't silently off.

🤖 Generated with Claude Code

Follow-up to #23. The guard's tailnet-IP and MagicDNS paths worked, but the **configurable public-IP / domain path silently did not block** — proven before the fix and after. ## The bug `leak-guard.sh` Check 3 ran `load_config_patterns | while …; done`. In POSIX sh the right side of a pipe is a subshell, so `HAS_LEAK=1` set there was lost: a public IP from `leak-patterns.conf` (e.g. the OSA endpoint that started this whole thread) was **printed but exited 0**. Checks 1–2 avoided it by using a here-doc, not a pipe. Fix: read the config into a variable and iterate in the main shell. ## Also in this PR - **Implement `LEAK_GUARD_SKIP=1`** — the BLOCKED message advertised it; the script never checked it. Now it does. - **`LEAK_PATTERNS_FILE` override** so the config path is testable. - **Exclude the guard's own files from scanning** (`leak-patterns.conf`, `leak-guard-selftest.sh`) — they hold detection patterns by design, so the guard would otherwise flag itself. Folded into a `SCAN_EXCLUDES` alongside the existing `.forgejo/` skip. - **`scripts/leak-guard-selftest.sh`** — asserts all six paths incl. the public-IP regression, wired as a CI step before the diff scan. Fixtures use RFC5737 / CGNAT / a zeroed tailnet name, so the test file leaks nothing real. - Remove the inert `__probe_test__.md` (placeholders + a "should block" comment but no real value — tested nothing) and the dead `check_pattern()`. ## Verified locally - self-test: 6/6 pass (incl. `public IP from config blocks`) - guard scanning this branch's own diff: clean (no self-flag) - guard in `--cached` mode blocks a staged tailnet IP (exit 1) ## Not in scope (wiring, needs the boxes) - Confirm the `freebsd` runner actually serves **layered-soul** — no `leak-guard` runs are recorded, and that runner was offline. Until a run goes green, don't make it a required check. - The pre-commit hook only activates per clone (`git config core.hooksPath .githooks`, or symlink). Worth a setup note/script so it isn't silently off. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(leak-guard): make config-pattern (public IP) check actually block
All checks were successful
leak-guard / guard (pull_request) Successful in 9s
ccd34bc78d
The Check 3 loop ran as `load_config_patterns | while ...`, a pipe
subshell, so HAS_LEAK=1 set inside it was lost — public IPs and domains
from leak-patterns.conf were printed but exited 0. Read the config into a
variable and iterate in the main shell instead.

Also:
- implement the documented LEAK_GUARD_SKIP=1 bypass (was advertised, never checked)
- allow LEAK_PATTERNS_FILE override so the path is testable
- exclude the guard's own config + self-test from scanning (they hold
  detection patterns by design)
- add scripts/leak-guard-selftest.sh covering all paths incl. the public-IP
  regression, wired into CI; fixtures use RFC5737/CGNAT/zeroed values so the
  test leaks nothing
- drop the inert __probe_test__.md fixture and dead check_pattern()

Verified: self-test green; guard clean on its own diff; blocks a real
tailnet IP in --cached mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
clawdie deleted branch fix/leak-guard-public-ip-block 2026-06-30 06:34:51 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
clawdie/layered-soul!24
No description provided.