fix(security): overwrite key/PIN files with fsync before deleting them

Two secure-delete paths overwrote a sensitive file and then unlinked it,
but neither reliably forced the overwrite to stable storage. The
plaintext key export used a buffered stream with only a flush, and the
PIN vault removal opened a second descriptor to fsync only on non-
Windows. On a crash, or on Windows, the zeroing write could stay in the
OS cache and the original bytes could survive on disk.

Both now go through one shared best-effort secure-delete helper:

- It overwrites the file in place in chunks, never truncating first, so
  the original blocks are the ones rewritten.
- It flushes the data to the device before unlinking (full fsync on
  macOS, write-through on Windows), then removes the file.
- It is safe on a missing file and reports whether the file is gone.

This is still best-effort: SSD wear-levelling and copy-on-write or
journaling filesystems may retain copies.

Tests exercise the overwrite-and-remove helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 19:24:12 -05:00
co-authored by Claude Opus 4.8
parent 63a422a615
commit 2a535c844d
5 changed files with 110 additions and 44 deletions
+9
View File
@@ -84,6 +84,15 @@ public:
*/
static bool deleteFile(const std::string& path);
/**
* @brief Best-effort secure delete: overwrite the file in place, flush, then unlink.
*
* Never truncates first (that would free the original blocks). Always attempts the unlink.
* SSD wear-levelling and CoW/journaling filesystems may retain copies.
* @return true when the file no longer exists
*/
static bool secureWipeAndRemove(const std::string& path);
/**
* @brief Write a file atomically and durably.
*