Skip to content

[bug] GenerateRpzAxfr full rebuild bypasses allowlist precedence (path-dependent served zone) #175

Description

@johanix

Severity: Medium · bug (correctness) · policy

GenerateRpzAxfr's denylist-emission loop emits every denylisted name directly, without consulting decide() / the allowlist:

for name := range pd.DenylistedNames {
    data[name+pd.Rpz.ZoneName] = &tapir.RpzName{ ... Action: pd.Policy.DenylistAction }
}

But decide() enforces the documented invariant "allowlist is absolute" (a name on any allowlist is never in the output, winning over deny and doubt). The incremental path (GenerateRpzIxfr) routes names through decide() and so honours it; the full rebuild does not.

Consequence: if a name appears on both an allowlist and a denylist (feeds disagree), the served zone diverges depending on the last operation:

  • after a full AXFR rebuild → the name IS in the zone (deny emitted directly), violating allowlist precedence;
  • after an incremental update → the name is NOT in the zone (allowlist wins via decide()).

So the served output is path-dependent and contradicts both decide() and the #156 design doc's invariant #1.

Origin: this is #156-lineage, not the #149 snapshot work — the old commented-out if pd.Allowlisted(k) filter at rpz.go:45 was never restored when the deny loop was rewritten. It is live on main (post-#156 merge).

Fix (separate PR off main):

  • Filter the denylist-emission through the allowlist check (or run each deny name through decide()), so allowlisted names are excluded from a full rebuild too.
  • Add a table-driven regression test: a name on allowlist + denylist must NOT appear in the published snapshot's Data after GenerateRpzAxfr (mirrors the existing TestDecide "allowlist beats deny and doubt" case, but at the rebuild level).

Found in the adversarial review of PR #174 (§2.3): docs/2026-06-03-pop-174-adversarial-review.md. Related: #156, #149/#174.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions