fix: clip sync timestamps, exclusive temp files, zeroized secret reads

- sync: timestamps and tombstones in the shared file are clipped to the
  local clock, and an edit wins a tie with a deletion, so a forged
  future-dated record can no longer override every later local change
  (or keep deleting a re-created profile) for as long as the forged date.
- write_private: the temp file is created O_EXCL under a random name, so a
  symlink pre-placed in a shared folder can't be followed or overwritten.
- Vault/keychain reads return Zeroizing<String>; has_sync_password is
  cached for a few seconds instead of fetching the real value every frame.
- generate_ssh_key creates a missing ~/.ssh as 0700.
- Honest wording: encrypted exports and the sync file carry login-script
  values; the audit entry, the Settings hint and the docs now say so.
This commit is contained in:
Andy Dixon
2026-10-13 00:36:06 +01:00
parent b6a7d51ddd
commit 76bd664ed1
10 changed files with 116 additions and 31 deletions
+2 -1
View File
@@ -452,7 +452,8 @@ impl Settings {
widgets::hint(
ui,
"Keep connection profiles in step across machines through a folder they share (a cloud drive, a network share, a git checkout). \
Profiles are stored there encrypted with the sync password; passwords and keys are never synced.",
Profiles are stored there encrypted with the sync password. Saved passwords and keys stay in each machine's keychain or vault; \
values a login script sends travel with their profile.",
);
form(ui, "sync-form", |ui| {
field(ui, "Folder");