harden: session-bus + liveness fail-closed, zbus tokio pin, root-only D-Bus checks (v0.3.6)#64
Merged
Merged
Conversation
… D-Bus checks (v0.3.6) Security hardening batch on visaged's authorization and runtime surface. No public API or D-Bus wire-format changes. - Root-only in-handler check on Enroll/RemoveModel/ListModels — defense in depth over the system-bus policy file alone (a missing/mis-scoped policy, or the session bus, could otherwise widen access). Skipped on the session bus. - VISAGE_SESSION_BUS=0 no longer enables session-bus mode (which skips D-Bus caller-UID validation). The env::var(..).is_ok() parse enabled it on ANY value — including "0", the natural way to turn it off — a fail-open trap. Now only a non-empty, non-"0" value opts in; unset/empty/"0" keep the secure system-bus default. - Passive liveness fails closed on fewer than 2 landmark frames. It previously reported "live" (fail-open), so a match backed by a single detectable landmark frame bypassed the gate. frames_per_verify defaults to 3, so a live subject in normal lighting is unaffected. - Pinned zbus to the tokio executor (default-features = false, features = ["tokio"]; pam-visage re-adds blocking-api) per zbus's own tokio-integration guidance. Removes the async-io / smol executor stack from the dependency tree and prevents a transitive dep from silently reverting the process to async-io. - Added an AES-256-GCM NIST known-answer test plus an on-disk blob-format guard (12-byte nonce, ciphertext, 16-byte tag, AEAD tamper rejection) so a future aes-gcm upgrade cannot silently change the format and orphan enrollments. Verified in the nix devshell: cargo build/test (79 tests) / clippy -D warnings / fmt all clean; feature audit confirms zbus no longer pulls async-io. Claude-Session: https://claude.ai/code/session_012wU47GVzskAummZqgH6FgF Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this solve?
A security-hardening pass over
visaged's authorization and runtime surface. Four issues, all defense-in-depth or fail-open → fail-closed corrections:Enroll,RemoveModel,ListModels) were root-only by the system-bus policy file alone. A missing, mis-scoped, or overly-permissiveorg.freedesktop.Visage1.conf— or running on the session bus — could let a non-root caller reach enrollment mutation or the enrollment listing.Verifyalready validated the caller UID in-process; these did not.VISAGE_SESSION_BUS=0enabled session-bus mode (which skips caller-UID validation). The flag was read withenv::var(..).is_ok(), so any value — including0, the natural way to turn it off — enabled it: a fail-open trap.check_landmark_stabilityreturned "live" when fewer than two landmark frames were available, so a match backed by a single detectable landmark frame bypassed the liveness gate.zbusran on its defaultasync-ioexecutor whilevisagedawaits tokio primitives inside#[zbus::interface]handlers — a latent "no reactor running" panic if a reactor-bound tokio call is ever added, and a transitive dep could silently revert the whole process toasync-io.What changed
Enroll/RemoveModel/ListModels(require_root_caller), skipped on the session bus, mirroringVerify.parse_session_bus: only a non-empty, non-"0"value opts in; unset/empty/"0"keep the secure system-bus default. Unit-tested.< 2landmark frames; surfaced as a rate-limited non-match.frames_per_verifydefaults to 3, so a live subject in normal lighting is unaffected.zbustotokio(default-features = false, features = ["tokio"];pam-visagere-addsblocking-api, which runs on zbus's internal tokio runtime). Drops theasync-io/smolstack from the tree.aes-gcmupgrade can't silently change the on-disk format and orphan enrollments.No public API or D-Bus wire-format changes (the
#[zbus(header)]/#[zbus(connection)]params are injected, not part of the wire signature). Bumps to v0.3.6.Testing
In the nix devshell:
cargo build,cargo test(79 tests, incl. new session-bus, liveness fail-closed, and crypto KAT/blob-format cases),cargo clippy --workspace -- -D warnings, andcargo fmt --all -- --check— all clean.cargo tree -e featuresconfirmszbusno longer pullsasync-io.