This report combines the architectural review (PROMPT-REVIEW.md) and the privilege boundary security review (PROMPT-SECREV.md) into a single, comprehensive analysis of the sudo-secretspec-cli codebase.
Overall, the design holds its primary security invariants—most notably the fail-closed value-free audit, the execvpe execution model, and the rollback-capable atomic mutations. However, two critical security violations were identified where the implementation deviates from the required specification.
Location: sudo-secretspec-cli/src/broker.rs -> require_boundary()
Issue: The require_boundary() function accurately verifies the vault (mode 0700, correct ownership, canonical path) and manifest/dotenv (mode 0600, correct owner). However, it fails to validate the binary and audit helper paths.
Violation: The function terminates without checking that the binary/audit helper exist, are not symlinks, and are owned by root:wheel with mode 755. This means a compromised operator might be able to manipulate the binaries if they somehow gain write access to the binary directories, bypassing the boundary checks.
Remediation: Add checks within require_boundary() to stat the executed binaries (e.g., /usr/local/libexec/sudo-secretspec and /usr/local/bin/sudo-secretspec) ensuring they are regular files, not symlinks, and are strictly root:wheel:755.
Location: sudo-secretspec-cli/src/install.rs
Issue: The installer does not derive the source root from the fixed libexec/../.. path structure as specified.
Violation: Instead, it relies on std::env::current_exe() and dynamically evaluates the manifest logic against itself using inline strings for auxiliary artifacts. This breaks the expected static release bundle structure, relying on the runtime path of the installer instead of the deterministic layout of the installation media.
Remediation: Update install.rs to derive the source root deterministically from the known installation target layout (libexec/../..) as per the specification.
require_root(): Correctly useslibc::geteuid() == 0to ensure root execution.- Operation Allowlist: Strictly limited to
source-*,audit-verify, andsource-template-check. - Reason Digestion: Empty reasons (
SHA-256("")) are explicitly rejected byis_valid_reason_digest(). - Fail-Closed Audit: Audit attempt is always written before ANY secret operation is performed.
- Mutation Safety: The
Mutationstruct correctly backs up manifest/dotenv to.rollback.<uuid>. Rollback failure forces the terminal audit toOutcome::Unknown. - Environment Isolation:
purge_ambient_env()safely purgesSECRETSPEC_*andXDG_*variables, and setsHOMEto/var/rootbeforeexecute()runs. - Provider Pinning: The dotenv provider is strictly pinned to
dotenv:///.../.env.
- Value-Free Guarantees:
AppendEventRequestmaps toAuditEventcarrying onlySHA-256(reason). No secret values are ever logged or transported as plain text into the ledger. - Hash Chaining:
event_hash = H(previous_hash || event_without_hash)is properly implemented. - Head Tracking: The
singleton=1row correctly tracks the(sequence, event_hash)tip. - Integrity Checking:
verify()correctly asserts the hash chain, the head match, and executesPRAGMA integrity_check. - Ownership: The ledger is properly
chowned to the vault owner when the broker runs as root.
- Report Safety:
Report.okcorrectly ignores advisory findings likeLEGACY_VAULT_CLUTTERandPENDING_ROLLBACK. - Vault Clutter:
.local,.ansible, and.cacheare properly categorized as advisory clutter. - Validation: Source manifest hashes are correctly verified against
MANIFEST.sha256. Sudoers syntax is validated usingvisudo -c. - Ancestor Chain: Validated to ensure root ownership, non-writability, and absence of ACLs.
- Realpath Checks: Vault is validated to resolve strictly under
/private/var/db/....
- Existing Adoption:
--adopt-existingsafely reads metadata but never chowns or chmods the vault. - Fresh Install: Correctly searches for an unused UID/GID in the 400-499 range and creates the vault at
0700. - Dry-Run Permissions:
require_root()is enforced before checking thedry_runflag. - Snapshot Scoping: Snapshots are strictly validated under
/usr/local/libexec/sudo-secretspec-rollback-*. - Restore Safety:
MANIFEST.sha256is validated before restore. Restores never touch the vault data. - Policy Safety: Sudoers policy changes are verified with
visudo -cpost-restore.
- No Shell Evaluation: Execution relies on
execvpesecurely without invoking a shell. - Reason Enforcement:
--reasonis required by Clap, and the plain-text reason is hashed by the client before being sent across the broker boundary. - Elevation: Install, rollback, and doctor commands elevate interactively using
sudorather than-n.
- TOML Parsing: Uses
deny_unknown_fieldsand properly validates the service identity pattern (^_[a-z_][a-z0-9_]{0,30}$). - Path Traversal: Rejects
..path traversal in managed paths. - Dependencies:
rusqliterelies on the system SQLite via Homebrew (nobundledfeature). - Homebrew Formula: Safe bootstrap process. The formula does not run
sudo, mutate/var/db, or edit sudoers.
The codebase exhibits a strong security posture, heavily leveraging Rust's type system to enforce privilege boundaries. The use of SQLite for an append-only hash-chained ledger is robust, and the execution funnel guarantees operations and audit records remain consistent. By addressing the missing binary metadata validations in broker.rs and fixing the source root path derivation in install.rs, this boundary application will fully meet its target design invariants.