v0.76.0: campaign-#3 hardening (settings .bak recovery, restore stack_name validation, quiesce marker quarantine)

S1: corrupt settings.json recovers from .bak / safe-defaults+preserve, no crash-loop.
F2: validStackName gates restore + export handlers (reject /,\,..,NUL traversal).
S3: corrupt quiesce marker logged + quarantined, not silently dropped.
Tests T-S1/F2/S3 + red-proofs. Agent/hub untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-22 23:34:33 +02:00
parent 141d51bf19
commit b0dd13154b
10 changed files with 305 additions and 2 deletions
@@ -166,6 +166,11 @@ func (s *Server) apiExportStart(w http.ResponseWriter, r *http.Request) {
jsonError(w, "Missing stack_name or dest_drive", http.StatusBadRequest)
return
}
// F2 (defense-in-depth): reject a traversal/escape stack_name before any export work.
if !validStackName(req.StackName) {
jsonError(w, "Invalid stack_name", http.StatusBadRequest)
return
}
if !s.isValidDrivePath(req.DestDrive) {
s.logger.Printf("[DEBUG] [web] apiExportStart: invalid drive path %q", req.DestDrive)