v0.61.0: audit fixes B1 (random temp staging) + D1 (mkfs wrapper member/RO re-checks) + D2 (empty-lsblk fail-safe) + D3 (blank-format anti-retarget)
From AUDIT-blast-radius-hostroot-localapi-2026-07-02.md. Each fix ships with a non-hollow test + a companion red-proof (shown failing on the pre-fix impl). Sudoers install-source grants became globs — deploy the sudoers drop-in with the binary. A1 (stale-lock pool-membership) deliberately excluded (spike). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -27,6 +27,35 @@ func antiRetargetResolve(
|
||||
resolve func(string) (string, error),
|
||||
derive func(string) (string, error),
|
||||
inspect func(string) (storage.DeviceProbe, error),
|
||||
) (string, error) {
|
||||
return antiRetargetResolveExpect(durableID, true, resolve, derive, inspect)
|
||||
}
|
||||
|
||||
// antiRetargetResolveBlank is the BLANK-format sibling [audit D3, AGENT-001's benign-branch twin]: the
|
||||
// same resolve → re-derive-match → re-inspect sequence, but it requires the re-inspected device to
|
||||
// STILL be blank (!DataBearing). The blank branch authorized mkfs precisely because the agent read the
|
||||
// device as having nothing to destroy; if the /dev node was reassigned in the window and now holds
|
||||
// data, the target changed — refuse rather than format it with neither a customer confirm nor a bound
|
||||
// durable id.
|
||||
func antiRetargetResolveBlank(
|
||||
durableID string,
|
||||
resolve func(string) (string, error),
|
||||
derive func(string) (string, error),
|
||||
inspect func(string) (storage.DeviceProbe, error),
|
||||
) (string, error) {
|
||||
return antiRetargetResolveExpect(durableID, false, resolve, derive, inspect)
|
||||
}
|
||||
|
||||
// antiRetargetResolveExpect is the shared core: resolve the bound durable id to the CURRENT device,
|
||||
// re-derive the device's durable id and require an exact match, then re-inspect and require the
|
||||
// data-bearing state to still be what the caller authorized (expectDataBearing). Returns the
|
||||
// re-resolved device to format — never a caller-supplied path.
|
||||
func antiRetargetResolveExpect(
|
||||
durableID string,
|
||||
expectDataBearing bool,
|
||||
resolve func(string) (string, error),
|
||||
derive func(string) (string, error),
|
||||
inspect func(string) (storage.DeviceProbe, error),
|
||||
) (string, error) {
|
||||
if durableID == "" {
|
||||
// A path-only binding is exactly what the durable id exists to prevent.
|
||||
@@ -50,11 +79,16 @@ func antiRetargetResolve(
|
||||
if !probe.Probed {
|
||||
return "", fmt.Errorf("%s did not probe cleanly at execution — refusing", device)
|
||||
}
|
||||
if !probe.DataBearing() {
|
||||
if expectDataBearing && !probe.DataBearing() {
|
||||
// The customer confirmed wiping a DATA-BEARING device; if it is now blank,
|
||||
// the target changed since confirmation — refuse rather than wipe blindly.
|
||||
return "", fmt.Errorf("%s is no longer data-bearing (target changed since confirmation) — refusing", device)
|
||||
}
|
||||
if !expectDataBearing && probe.DataBearing() {
|
||||
// The agent authorized a BLANK format; the device is now data-bearing —
|
||||
// the target changed since inspection (D3 re-enumeration race) — refuse.
|
||||
return "", fmt.Errorf("%s is now data-bearing (target changed since blank inspection) — refusing", device)
|
||||
}
|
||||
return device, nil
|
||||
}
|
||||
|
||||
@@ -69,3 +103,14 @@ func (s *Server) reresolveDurableForWipe(ctx context.Context, durableID string)
|
||||
func(dev string) (storage.DeviceProbe, error) { return s.disks.InspectDevice(ctx, dev) },
|
||||
)
|
||||
}
|
||||
|
||||
// reresolveDurableForBlankFormat wires antiRetargetResolveBlank with the real storage funcs and the
|
||||
// server's disk inspector (audit D3 — the blank-format branch's pre-mkfs anti-retarget re-check).
|
||||
func (s *Server) reresolveDurableForBlankFormat(ctx context.Context, durableID string) (string, error) {
|
||||
return antiRetargetResolveBlank(
|
||||
durableID,
|
||||
storage.ResolveDurableDevice,
|
||||
storage.DeviceDurableID,
|
||||
func(dev string) (storage.DeviceProbe, error) { return s.disks.InspectDevice(ctx, dev) },
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user