Network → service
Untrusted requests enter the monitored service.
Security / Threat model
fail2zig parses attacker-influenced logs and changes kernel firewall state. This STRIDE model documents the threats, the controls in place, and the risks those controls leave behind.
Scope
The enforcing daemon needs firewall privileges. An all-log-only configuration can run unprivileged. In either mode, the daemon relies on trusted host components and service records.
Architecture
The numbered transitions connect the data flow to the threat register. The administrative and telemetry interfaces form separate boundaries into the daemon.
Crafted requests and floods
sshd, nginx, postfix
Files or journal output
Receipts → detection → durable intent
Selected enforcement backend
TB-05Local client → IPCSocket permissions + peer credentials
TB-06HTTP caller → telemetryLoopback by default; optional in v0.4.0
Trusted configuration governs the daemon (A.02). nftables uses direct netlink; ipset and iptables use argv-based subprocesses. Explicit backend selection is available in v0.4.0.
Untrusted requests enter the monitored service.
Service interpretation becomes the evidence used for ban decisions.
Attacker-influenced bytes enter bounded parsing, durable receipts and native policy.
CAP_NET_ADMIN authorizes changes to firewall state.
Peer credentials determine access to daemon administration.
Bind restrictions limit access to read-only operational state; they do not authenticate callers.
STRIDE / 6 categories / 18 threats
Every entry preserves its reference ID and affected boundary or assumption. Implementation details remain available beneath the mitigation and limitation.
Boundary TB-05
0660. The shipped daemon runs as fail2zig; its configured service/monitor group has read-only access. Mutations require uid 0 or the daemon UID, checked through SO_PEERCRED. The installer can select a custom group.Boundary TB-02
Assumption A.02
0640, owned root:fail2zig — an unprivileged attacker cannot write it, and the daemon enforces it: a world-writable or non-root-group-writable config is refused at load with its mode and the chmod 0640 fix (SEC-012); a non-root owner warns. Modifying it requires root, which is outside this model's attacker (A.04) and covered by the filesystem-integrity assumption (A.02). Config validation runs at startup, before any firewall or event-loop state change, so a malformed config fails closed rather than partially applying.Assumption A.02
Boundary TB-02
Boundary TB-05
fail2zig history provides paginated confirmed history. Administrative mutations return structured outcomes and revisions, distinguishing installed, partial and uncertain effects. Required recovery anchors stay pinned during retention. External audit retention needs its own protected storage and policy.Boundary TB-06
/api/health reports HTTP 200 when ready and 503 otherwise. Remote exposure needs operator access controls; disabling HTTP leaves IPC monitoring available.Boundary TB-05
Boundary TB-03
info-level output; full per-line decisions are only logged at debug.Boundary TB-03
Boundary TB-03
Boundary TB-05
Boundary TB-06
metrics_enabled = false removes their listeners while retaining IPC. Keep loopback binding or apply external access controls. A connected stream is not proof of enforcement readiness.Boundary TB-04
global.firewall selects the backend; an explicit selection never falls back. Automatic detection stops on permission denial. Unusable required enforcement refuses startup by default; explicit on_no_backend = "log-only" permits degraded observation. Overlapping jail owners retain independent protection. Effects stay in the current network namespace; custom selectors are unsupported.Boundary TB-03
CAP_NET_ADMIN, CAP_NET_RAW and CAP_DAC_READ_SEARCH. NET_RAW permits raw IP sockets; AF_PACKET is excluded. Filesystem/syscall restrictions and NoNewPrivileges narrow authority, but there is no separate unprivileged HTTP process.Boundary TB-02
ignoreip CIDRs always win. These controls depend on the service keeping attacker-controlled text separate from authoritative source-IP fields.Boundary TB-05
Assumption A.02
SHA256SUMS and a SLSA build-provenance attestation, verifiable with gh attestation verify. GitHub Actions are pinned to full commit SHAs. These provide artifact integrity and provenance checks; byte-identical rebuilds are not claimed.Operational behavior
Startup refusal, explicit degradation, and state recovery are different outcomes. These are the behaviors an operator should expect.
Exit with a cause by default. Explicit on_no_backend = "log-only" permits DEGRADED observation.
D-05 ↗Refuse unusable native state; restore coherent state and source continuity before healthy admission.
T-02 ↗Pause affected admission or report degraded health; retain critical receipts, owners and unresolved intent.
D-01 ↗Report failed, partial or uncertain effects; confirm installed protection through owned-kernel readback.
D-05 ↗Assurance
Engineering checks and release provenance provide evidence. An independent security audit remains planned.
Durable SQLite state, owned-kernel readback and read-only monitoring-group access. Selected live checks used Debian 13 x86_64 before the version-only release update; rebuilt artifacts passed native/emulated checks. Keep default loopback ignores: matching loopback SSH failures can lead to storage intervention in this release.
Parser, IP, IPC, and TOML fuzz harnesses are part of the test suite. Allocator-failure testing exercises failure paths; test coverage is not proof of absence of defects.
Published checksums and SLSA attestations support artifact verification. The release verification job re-downloads and checks artifacts; byte-identical rebuilds are not claimed.
Planned scope: parsing, allocator boundaries, privileges, firewall backends, and IPC authorization. Sponsor and schedule remain unconfirmed.
Published findings and disclosure records: GitHub security advisories ↗. The engine repository publishes its own threat model document ↗ with each threat’s severity, control and the decision record behind it.
Responsible disclosure
Use GitHub’s private advisory form so maintainers can assess the issue and coordinate a fix before public disclosure.