diff --git a/CHECKPOINT-encryption.md b/CHECKPOINT-encryption.md index 4f2fe91..dbc93c4 100644 --- a/CHECKPOINT-encryption.md +++ b/CHECKPOINT-encryption.md @@ -1,4 +1,4 @@ -# Checkpoint — Header-based CSP + navigation guards (2026-08-21) +# Checkpoint — Legacy vault permission hardening (2026-08-21) A stopping point you can return to if this session is closed. Everything below was verified green at the moment this file was written. @@ -6,12 +6,12 @@ verified green at the moment this file was written. ## Where things are - Project: `/home/avi/Projects/0_Nostr` -- Git repo: `master` @ `4d4dfde` ("Enforce header-based CSP and block window open/navigation"). - Before it: `6e627a3` (upload pick tokens), `4bde395` (IPC allowlist), then checkpoint - commits, on top of contact-aware feed (`a1445d1`) etc. +- Git repo: `master` @ `4bd7660` ("Tighten permissions on leftover legacy vault files"). + Before it: `4d4dfde` (CSP + navigation guards), `6e627a3` (upload pick tokens), + `4bde395` (IPC allowlist), on top of contact-aware feed (`a1445d1`) etc. - Working tree is **clean** apart from this checkpoint update, which is committed right after. -## What was completed: security hardening items #1, #2 and #3 +## What was completed: security hardening items #1–#4 Fixes from the 2026-08-21 security audit. @@ -55,8 +55,23 @@ page could read+publish arbitrary local files to nostr.build. Now: - `setWindowOpenHandler`: all `target="_blank"` popups are denied; external links go to the system browser. Unknown schemes are denied without opening anything. +**#4 Legacy vault permissions (`4bd7660`):** +- The original CLI left `profiles_vault.json` files with default (often group-readable) + permissions containing plaintext keys. Now: + - On **every** startup, `load_vault()` calls the new `harden_stray_legacy_vaults()` + (`src/vault.rs`): each known legacy location is checked, and any file that parses as a + populated vault is chmod'd to 0600 — whether or not migration ever runs. + - During migration itself, the legacy file is tightened before the backup copy is made. + - Hardening is best-effort (`let _ =`) so odd filesystems can never break vault loading; + unparsable and keyless files are deliberately not touched. +- One-time local cleanup done by hand in this session: repo-root `profiles_vault.json` + was chmod'd from 0664 → 0600. +- New tests: recognised legacy vault tightened to 0600; unparsable file ignored; empty / + encrypted-but-populated vaults classified correctly. + ## Commits +- `4bd7660` "Tighten permissions on leftover legacy vault files" — src/vault.rs (+79/−3). - `4d4dfde` "Enforce header-based CSP and block window open/navigation" — main.ts + index.html. - `6e627a3` "Replace upload file paths with single-use pick tokens" — main.ts, api.ts, types.ts, AppProvider.tsx, ComposeScreen.tsx, fakeBackend.ts (+62/−27). @@ -97,10 +112,11 @@ Manual protocol checks worth doing once: Remaining audit items in priority order: -1. **Legacy vault perms** — repo-root `profiles_vault.json` is group-readable (0664); - chmod 600 / delete after confirming migration; auto-tighten during migration in `src/vault.rs`. -2. **Write-race fixes** — create files with mode 0600 at creation time in `vault.rs` - (`write_restricted`, `backup_file`). -3. **Zeroize** — wipe decrypted key material via the `zeroize` crate. -4. Smaller: link-preview SSRF guard (block loopback/private IPs), signer pending-cap, +1. **Write-race fixes** — create files with mode 0600 at creation time in `vault.rs` + (`write_restricted`, `backup_file` currently chmod after creating). +2. **Zeroize** — wipe decrypted key material via the `zeroize` crate. +3. Smaller: link-preview SSRF guard (block loopback/private IPs), signer pending-cap, NIP-46 secret echo check, backend request timeout. + +All four high/medium user-facing findings from the audit are now closed (#1 IPC allowlist, +#2 upload tokens, #3 CSP + navigation, #4 legacy vault perms).