Date: 2026-10-03, after sign-off runs S1-S3 on the real system. Three
reviewers (AI agents), each in its own clone with its own sc build and
throwaway stores. The real scd, store and /etc were not touched:
validators ran as root only through sc check --as and sudo unshare
--mount probes that bind-mounted fabricated files in a private
namespace. The three areas were security and content leaks, checker
correctness against the real consumers, and operations (long runs,
bursts, sc edit and restore against scd, standing in for the soak cut
short). Claude reproduced each high and medium finding before fixing it.
Gate: no high-severity finding open. The checker reviewer found two
high ones; both are fixed (297fbc7). Six of the 7 medium findings
are fixed (297fbc7, bb31f3e), and so are 7 of the low ones and a
cleanup. The rest go on the M3 follow-up list in MILESTONES.md.
Two departures from the review rules, both read-only: the checker
reviewer ran sudo grep -c and sudo wc -l on the real sudoers files
(line counts only), and the security reviewer left one root-owned strace
output in its scratch directory. Claude deleted it unread.
PATH and LC_ALL=C, with no
SUDO_* or SSH_AUTH_SOCK. Tools come from fixed directories with no
shell. Children in the tool’s group are killed. Traced runs of the 11
validators showed no network use, and no writes outside the scratch
copy except the unit checker’s man pages (now --man=no).Added never re-blames an old
finding for inserted lines. With no validator, sc’s own rules run with
a note. All explanations are 2-5 lines of at most 76 columns.sc edit racing a real watcher gave exactly the rows the plan
promises.make m1-compat passes.sc check as root finds no problems in 24 files, on
the S2 build and on the fixed one.| Area | Finding | Severity | Fixed in |
|---|---|---|---|
| fstab | A source that is a path outside /dev was never checked. A missing bind-mount source, loop image or swap file gave “no problems found”, yet the mount fails at boot and the machine stops in emergency mode. Reproduced with findmnt and systemd-fstab-generator. |
high | 297fbc7: the path must exist, at the line’s severity; a path below another line’s mount point is not looked for |
| accounts | An emptied or admin-less /etc/passwd, /etc/group or /etc/sudoers passed, and an empty passwd was only a warning (since C8). Each locks Ubuntu’s owner out, shown with sudo in a private mount namespace. |
high | 297fbc7: passwd-no-admin, group-no-admin, sudoers-no-rules (blockers) |
| runner | A relative SC_HOME or TMPDIR made every validator miss its input, giving a false clean. sc edit saved a broken sudoers file. |
medium | bb31f3e: scratch paths are absolute |
| scd | A validator that timed out counted as a clean run: “ok again” for a file still broken, then the old problem blamed on the next change. sc check said “no problems found”. |
medium | bb31f3e: Report.Incomplete; scd logs no “ok again” and does not cache the result; sc check exits 1 |
| group | A member of sudo or admin who is not a user (a typo, a CRLF) was a warning, but whoever was meant loses sudo. | medium | 297fbc7: error |
| nsswitch | A group, shadow or initgroups line without files was an error or nothing, but each ends sudo. | medium | 297fbc7: blockers |
| fstab | fstab-verify (a findmnt [E] with no rule of sc’s) was always a warning, though the mount fails. |
medium | 297fbc7: the line’s own severity |
| grub | sh -n accepts an unquoted value with a space and spaces around =, but update-grub stops on both. |
medium | 297fbc7: sc’s own lines, checked against dash |
| units | Unit drop-ins (*.service.d/*.conf) have no checker. |
medium | deferred (follow-up 1) |
| fstab | x-systemd.automount with a missing device was a false blocker: only the automount is required at boot. |
low | 297fbc7: error |
| sudoers | A bad mode on /etc/sudoers itself was an error, but sudo then refuses to run. |
low | 297fbc7: blocker |
| preload | preload-missing-lib was a blocker, but the loader prints an error and runs the program. |
low | 297fbc7: error |
| keys | An sshd or unknown-unit-key mistake added above an identical old one blamed the old line. | low | 297fbc7: keyed by the line |
| units | systemd-analyze verify ran man and groff, as root under scd, for Documentation=man: entries. |
low | 297fbc7: --man=no |
| scd | After sc restore or sc edit fixed a reported file, scd said nothing, and a later unrelated change logged “ok again” with its id. Seen at S3. |
low | bb31f3e: the restore or edit gets the “ok again” (the operations reviewer’s tested fix) |
| scd | A full check queue named only the first dropped file. | low | bb31f3e: it says how many files were dropped |
| runner | check-* scratch copies left by a killed sc were never removed. |
cleanup | bb31f3e: swept after an hour |
| sshd | ListenAddress naming an address this machine does not have passes sshd -t, but SSH is gone at the next boot. |
low | deferred (2) |
| sshd | A drop-in valid only together with the main file is a false blocker when checked alone. | low | deferred (3) |
| notes | Some notes carry a validator’s raw line without -v. They never reach the journal. |
low | deferred (4) |
| signals | Ctrl-C or SIGTERM to sc check leaves a running validator and its scratch copy. The copy is now swept after an hour. |
low | deferred (5) |
| rescue | With no writable scratch directory (a read-only root), sc check runs none of its rules. |
low | deferred to M4 (6) |
| scd | Each check lists a path’s whole history: 0.1 s at 20,000 rows. | cleanup | deferred (7) |
| grub, fstab | An unclosed quote is reported past the last line; two swap lines share one findmnt heading. | cleanup | deferred (8) |
New or extended:
TestFstabPathSources, TestFstabPathSourceUnreadable.TestAdmins, TestGroupMemberSeverity, TestSudoersNoRules,
and initgroups cases in TestNsswitch.TestShAssignments, which checks every case against dash.TestSshdKeys and TestUnitKeys.TestScratchAbsoluteAndSwept, TestReportIncomplete.TestCheckIncomplete, TestCheckRestoreOkAgain, and the drop count
in TestCheckQueueBound.TestCheckCLIIncomplete, TestCheckCLIRelativeHome.Mutation checks on the unit key, the incomplete handling and the absolute
scratch path each fail their test. All tests pass as a user, as root and
under race, and CI is green on bb31f3e. accept-m3.sh gained cases for
the new rules and passed as root on bb31f3e.