| 1 | | Round-1 finding | Disposition | Reason | |
| 2 | |---|---|---| |
| 3 | | 1. Scanner role can read parameters | **Closed** | §3.1 now requires an explicit deny covering all four parameter-read actions on every resource. | |
| 4 | | 2. Masked socket prevents clamd startup | **Closed** | §3.2 now requires a complete replacement service without `Requires=` or `Also=` referencing the socket. | |
| 5 | | 3. Foreground FreshClam conflicts with package-started daemon | **Closed** | Package starts are suppressed; the foreground initialization completes before the updater service starts. | |
| 6 | | 4. Incomplete scans can be recorded as clean | **Partly closed** | `AlertExceedsMax` and the new mapping address limit-only replies. A limit can still be hidden by a malware signature, violating D8; see finding 6. | |
| 7 | | 5. SSM administration lacks an installed agent | **Closed** | Installing and enabling the arm64 SSM agent is now the first bootstrap step. | |
| 8 | |
| 9 | Reviewed draft 2 at `05752422`. These are design dispositions; no files changed or live tests performed. |
| 10 | |
| 11 | 6. **P2 — §§3.2, 4.3, 7: A malware signature can hide an earlier limit hit.** |
| 12 | |
| 13 | ClamAV’s default `HeuristicScanPrecedence no` allows scanning to continue after a heuristic detection and gives a subsequent malware detection precedence. Limit indicators use that heuristic path: [libclamav/others.c:1045,1354](https://raw.githubusercontent.com/Cisco-Talos/clamav/clamav-1.4.3/libclamav/others.c). The precedence behavior is documented in the [trixie configuration manual](https://manpages.debian.org/trixie/clamav-daemon/clamd.conf.5.en.html#HeuristicScanPrecedence). |
| 14 | |
| 15 | An archive with an oversized member followed by a detectable EICAR member can therefore produce a malware `FOUND` reply without the limit prefix. The proposed case never matches; [internal/clamd/clamd.go:280](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/clamd/clamd.go:280) still classifies it as infected, and [internal/objstore/clamav.go:364](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/objstore/clamav.go:364) signs that verdict. This contradicts D8’s required result for an object known to have been partly scanned. The zeros-only proof does not exercise this combination. |
| 16 | |
| 17 | **Fix:** Ensure an encountered limit survives to the client—configure and test heuristic precedence, or carry completion evidence separately from the selected signature. Add a mixed oversized-member/EICAR archive to §7 and require `unscanned`. |
| 18 | |
| 19 | 7. **P2 — §4.3: Mapping scan-time exhaustion to `skipped` makes a temporary timeout permanent.** |
| 20 | |
| 21 | `StatusSizeExceeded` becomes `VerdictSkipped`, but [internal/objstore/clamav.go:249](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/objstore/clamav.go:249) retries only `denied` and `failed`. An unchanged, signed `skipped` verdict is returned indefinitely. [internal/objstore/sweep.go:241](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/objstore/sweep.go:241) calls the engine only for `unknown`. |
| 22 | |
| 23 | Consequently, one `MaxScanTime` result during scanner contention permanently excludes that object from scanning, even after recovery or a timeout increase. Raising extraction limits likewise does not retry archives skipped under the previous settings. |
| 24 | |
| 25 | **Fix:** Preserve D8’s `unscanned` classification while defining retry behavior for engine-limit results. For example, retry skipped objects on subsequent sweeps, retaining the existing size check before fetching. Add a two-sweep test: limit refusal first, successful scan second, with unchanged object bytes. |
| 26 | |
| 27 | 8. **P2 — §6.2: Ship/promote does not establish the new console’s running-version precondition.** |
| 28 | |
| 29 | Direct promotion only writes the channel pointer: [internal/release/release.go:718](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/release/release.go:718). Adoption happens separately and can defer or fail staging: [internal/release/adopt.go:956](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/release/adopt.go:956). Restarting `console.service` before adoption therefore restarts the old executable, now with the scanner wired. |
| 30 | |
| 31 | The header check occurs after wiring and has no explicit expected-build or success-status gate. Moreover, the edge supplies `X-Carlos-Version` from its route state: [internal/edge/edge.go:2192](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/edge/edge.go:2192). For an unstamped console unit, adoption can advance that state without restarting the actual console process; see [internal/host/agent.go:2898](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/scanner-host/internal/host/agent.go:2898). |
| 32 | |
| 33 | **Fix:** Before changing scanner environment variables, require adoption of the exact console artifact containing §4.3, completion of the console process restart, and a successful response identifying that build. Make failure stop the sequence before wiring or enabling scanning. |
| 34 | |
| 35 | **Verdict: accept with fixes.** |