You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Scope 1 shipped in #318 on 2026-09-01. Read this as an HMAC issue.
Verified at 30b9e315 on 2026-09-17: docs/cli.md:167 and docs/the-audit-chain.md:404 both state the confidentiality class, and tests/release/audit-export-confidentiality.test.sh fails if the two calls
below ever swap order. What is left is Scope 2, which needs an HMAC over the
request and a chain_version bump, so the hard half is the whole issue now.
The two line numbers have also moved twice. At 30b9e315 they are dispatcher.rs:2224 (compute_request_hash) and dispatcher.rs:2264
(redact_params), not the 2001 and 2041 the paragraph below quotes.
request_hash is a column of every signed chain row, and sysknife audit export (#260) now serialises it. The hash commits to the unredacted request:
crates/sysknife-daemon/src/dispatcher.rs:2001 let request_hash = compute_request_hash(action_name, params);
crates/sysknife-daemon/src/dispatcher.rs:2041 let redacted_params = redact_params(action_name, params);
Redaction runs 40 lines after the hash, and compute_request_hash is one unsalted round:
For ConfigureWifi the credential params are password and ssid. The SSID is broadcast, so the only unknown in the preimage is the passphrase, and a single unsalted SHA-256 is the cheapest thing a GPU cracks. The daemon keeps the database 0600 inside a 0700 directory precisely so this content does not travel; an export moves it across that boundary by design, into a SIEM, a ticket, or an auditor's laptop.
High-entropy credentials such as ProAttach tokens are unaffected. The problem is the low-entropy human-chosen ones.
The column cannot simply be dropped: request_hash is part of ChainContent::canonical_bytes (crates/sysknife-daemon/src/audit_chain.rs:508), so an offline verifier needs it to rebuild the signed bytes.
Scope
Two parts, and the first is the one that matters today:
Say plainly in docs/cli.md and docs/the-audit-chain.md that an export inherits the database's confidentiality class and is not a redacted artifact. Done in feat(cli): export audit chain rows as JSON #318 on 2026-09-01, guarded by tests/release/audit-export-confidentiality.test.sh.
Consider replacing the bare hash with an HMAC keyed by the audit key. That keeps the binding an offline verifier needs while removing the offline-crackable commitment, at the cost of a chain_version bump and a verifier that has the key.
Tests first
Part 1's guard is on main already. For part 2, a round-trip test that an HMAC-bound row still verifies, plus a migration test across chain_version, and a negative case: a row written under the old chain_version must still verify after the change, or the bump has silently invalidated every existing trail.
Difficulty
hard. The documentation half that made this medium has shipped. What remains touches the signed encoding, so it needs the HMAC, a chain_version bump and a verifier that holds the key.
Getting started
CONTRIBUTING.md has the build and test commands, and docs/developer-guide.md covers the setup steps and how to reproduce each required check locally. No CLA and no copyright waiver. The project is MIT.
request_hashis a column of every signed chain row, andsysknife audit export(#260) now serialises it. The hash commits to the unredacted request:Redaction runs 40 lines after the hash, and
compute_request_hashis one unsalted round:Why it matters
For
ConfigureWifithe credential params arepasswordandssid. The SSID is broadcast, so the only unknown in the preimage is the passphrase, and a single unsalted SHA-256 is the cheapest thing a GPU cracks. The daemon keeps the database 0600 inside a 0700 directory precisely so this content does not travel; an export moves it across that boundary by design, into a SIEM, a ticket, or an auditor's laptop.High-entropy credentials such as
ProAttachtokens are unaffected. The problem is the low-entropy human-chosen ones.The column cannot simply be dropped:
request_hashis part ofChainContent::canonical_bytes(crates/sysknife-daemon/src/audit_chain.rs:508), so an offline verifier needs it to rebuild the signed bytes.Scope
Two parts, and the first is the one that matters today:
Say plainly inDone in feat(cli): export audit chain rows as JSON #318 on 2026-09-01, guarded bydocs/cli.mdanddocs/the-audit-chain.mdthat an export inherits the database's confidentiality class and is not a redacted artifact.tests/release/audit-export-confidentiality.test.sh.chain_versionbump and a verifier that has the key.Tests first
Part 1's guard is on
mainalready. For part 2, a round-trip test that an HMAC-bound row still verifies, plus a migration test acrosschain_version, and a negative case: a row written under the oldchain_versionmust still verify after the change, or the bump has silently invalidated every existing trail.Difficulty
hard. The documentation half that made thismediumhas shipped. What remains touches the signed encoding, so it needs the HMAC, achain_versionbump and a verifier that holds the key.Getting started
CONTRIBUTING.md has the build and test commands, and docs/developer-guide.md covers the setup steps and how to reproduce each required check locally. No CLA and no copyright waiver. The project is MIT.