Skip to content

firewall: verify pf's main ruleset references the janus anchor - #71

Merged
shreeve merged 1 commit into
mainfrom
firewall/anchor-reference
Oct 11, 2026
Merged

shreeve merged 1 commit into
mainfrom
firewall/anchor-reference

Conversation

@shreeve

@shreeve shreeve commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

checkPf checked that pf is enabled and that the janus anchor holds exactly the anchor file's rules. It never checked that pf's main ruleset still references the anchor. After pfctl -F all, or a pfctl -f of a file without anchor "janus" (a VPN client, a hand reload), the anchor's rules stay loaded but are never evaluated. The host was then wide open while sudo janus status said verified. The #60 pf-verifier draft lists this as its finding 6.

Change

  • Check: checkPf requires pfctl -sr to list anchor "janus" before anchor "com.apple/*" (pfReferenced). Otherwise the verdict is "pf's main ruleset does not evaluate the janus anchor ahead of Apple's".
  • Repair: applyPf used to reload only the anchor whenever pf.conf was already wired, so sudo janus firewall could not fix a flushed reference, and with the new check it would just fail. It now reloads /etc/pf.conf when the reference is gone (pfctl -nf first, then pfctl -f), leaving the file untouched. This is the repair the Draft contracts: confine, metrics, trust bootstrap, auth session lifetime, pf verifier #60 draft specifies for this failure.
  • Docs: the exposure-modes contract, README, and CHANGELOG state the added condition.

Tests

  • TestCheckPfVerdicts covers an empty main ruleset, a reference behind Apple's anchor, and anchor "janus/sub", which is not the anchor.
  • TestApplyPfRestoresTheReference covers wired pf.conf with a flushed ruleset: the check fails, then apply parse-checks, reloads pf.conf without rewriting it, and the result verifies.
  • The fake host's pfctl -sr now lists the filter anchors of whichever pf.conf was last loaded (or the booted one).
  • make test: unit suites pass and acceptance passes 174/174 in the foreground; go vet passes for linux and windows.

Not verified on a live host. pfctl -sr needs root. Its anchor "name" all format is pfctl's standard listing, but the next sudo janus status on a macOS edge is the first real check.

@shreeve
shreeve force-pushed the firewall/anchor-reference branch from 0e2bdf2 to b16828b Compare October 11, 2026 12:32
…nd reload pf.conf when it does not

pfctl -F all, or a pfctl -f of a file without the reference, leaves the
janus anchor's rules loaded but never evaluated; checkPf compared only
the anchor's rules and called that verified. It now requires pfctl -sr
to list anchor "janus" ahead of anchor "com.apple/*", and applyPf
reloads /etc/pf.conf (parse-checked) when the reference is gone, even
with pf.conf already wired.
@shreeve
shreeve force-pushed the firewall/anchor-reference branch from b16828b to b206ed4 Compare October 11, 2026 13:46
@shreeve
shreeve merged commit 822b594 into main Oct 11, 2026
4 checks passed
@shreeve
shreeve deleted the firewall/anchor-reference branch October 11, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant