Skip to content

Memory: unguarded DELETE /api/memory/banks/{id} enables one-call data loss (RCA + hardening) #1024

Description

@thinmintdev

Summary

On 2026-07-04 an agent misidentified the live Hindsight banks as orphaned and issued DELETE /api/memory/banks/{bank_id}, irreversibly cascade-deleting ~632 records across private__hermes-agent (275 facts), private__hermes, and shared. Recovered from a PBS backup.

Root cause

DELETE /api/memory/banks/{bank_id} (src/hal0/api/routes/memory_admin.py, _FORWARDS) is a bare passthrough to Hindsight with no confirmation, no soft-delete, no auth. The entire /api/memory/* surface is unauthenticated and bound on 0.0.0.0:8080, so any LAN host — or an agent's terminal/tool — can wipe a bank with one curl, bypassing the UI confirm dialog. Contributing UX bug: the dashboard mislabels the banks (colon vs double-underscore spelling; list?bank returns wrong data) which fed the misdiagnosis.

Fixes (branch fix/memory-tab-functional, hotpatched on CT105)

  • DELETE /banks/{id} now requires ?confirm=<bank_id> (or body {"confirm":...}); mismatch → 400, no forward.
  • GET /api/memory/list?bank= alias mapped to dataset (was silently returning default-dataset rows).

Remaining hardening (this issue)

  • Reintroduce write-auth (bearer or localhost-only) on mutating /api/memory/* routes; keep reads open if desired.
  • Soft-delete / tombstone for banks (rename + TTL purge) so deletes are reversible.
  • Audit-log every destructive memory op.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions