v0.15.1 — block stored memory-injection
Hardening
Two complementary fixes for stored / indirect prompt-injection via the memory store. A low-trust write — most realistically an agent's MCP memory_add, since the store is shared across agents — could plant a memory that hijacks the trust-bearing content injected at the start of every session.
- Delimiter forgery on write blocked — a memory
body/summarywas serialized verbatim into the delimiter-based record format, so one write could forge a second record, or self-escalate its own, topriority: critical(injected at the top of every session, and, ifprotected: true, undeletable from the UI).render_record/render_from_metanow fold summary line breaks and backslash-escape any body line that matches the record delimiters (START_RE/END_MARK) — the single choke-point every write path (CLI, MCP, web, consolidation) passes through. Legit###/- key:body content is left untouched and the escape is idempotent, so edit / re-scope / merge re-renders don't double-escape. - Heading forgery in the SessionStart hook blocked — a 2-space indent does not neutralize an ATX heading (CommonMark allows 0–3 leading spaces), so a normal memory body containing
## Critical rules (mandatory in every task)could forge one of the hook's own trust-bearing sections. All three body-emit paths (profile, critical, budgeted) now route through_body_lines, which escapes any#-leading line.
No API, config or store-format changes; ordinary notes render identically.