From 76b21b3597087f727d6b20a2d869474e882a482c Mon Sep 17 00:00:00 2001 From: Mix Date: Thu, 15 Oct 2026 10:38:44 +0300 Subject: [PATCH] audit 3: the reviews' findings and what was accepted, in the plan Co-Authored-By: Claude Opus 5.5 --- docs/audit-2026-10-12.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/audit-2026-10-12.md b/docs/audit-2026-10-12.md index e249cae..438f5b6 100644 --- a/docs/audit-2026-10-12.md +++ b/docs/audit-2026-10-12.md @@ -1155,6 +1155,34 @@ those after it move up one patch number each. `-o`); guide § Restore (step 1), § Full backup (certs/, `-o`, the database) and § Encrypting (the first block, a cut file, the floor). +*Changed by the reviews of stage 3 (2026-10-15; technical and security, +reports in the session's scratchpad):* **H1** - a restore of a server with +DMARC on was refused on every start: the archive records no owner, tar as +root leaves the files root's, and the entrypoint handed back to the panel +only the maps it named, not the three DMARC maps, which the comparison then +could not read; the entrypoint now hands every file beside `queue/` in +`/data/postfix` to `panel:selfpost` 0640 (e2e: an extra map written before +the backup, unpacked as root, `panel:selfpost 640` after). The comparison +reads regular files only (`Lstat`, size first, `LimitReader`: a link or a +pipe in a crafted archive is refused, not followed or waited on); a record +unpacked again wins over the mark of an earlier check, and ConsumeRestore +removes both; the mark is synced; a `selfpost.db-wal/-shm/-journal` beside a +freshly unpacked database is refused. `secretfile`: r ≤ 64 as well (N=2 +with a huge r asked 384 MiB of B and XY). The panel names an empty `certs/` +(`backup.ErrNoCerts`) instead of "could not read". `AttachRefusalLine` +refuses an empty line, as the old statement did. A skipped entry's kind in +words. `-decrypt` of an empty payload is not a failure. Guide: the shell's +`>` empties the file before a wrong password is found, a killed CLI leaves +`.NAME.tmp-*`, unpack again into an empty directory, the comparison is made +once, and step 2 of the in-place restore stepped out of `.` (`mv .` fails; +older than this stage). Accepted, with the reason: hashing every `data/` +file delays the first restore start - SHA-256 runs at hundreds of MB/s and +the database measured on the test server is under a megabyte (a 30-day +journal at 1 900 messages a day is tens of MB), well inside Postfix's wait +for the milter sockets; a CLI killed by SIGKILL cannot clean its temporary +file, and a handler for the gentler signals buys little for a one-off +command whose leftover is the owner's alone. + ### Stage 4 — panel behaviour (M8, M11, L10–L19) → `2.5.4` - [ ] Login: dummy bcrypt on unknown user; a test that measures both paths within