Context
PR #485 review (item 2) flagged that f\"{AGENT_NAMESPACE_PREFIX}{agent_id}\" does not validate agent_id before concatenation. Hostile-shaped values like foo:bar, ../x, or whitespace produce malformed-but-stored namespace strings ("agent-runtime:foo:bar", etc.) that round-trip into storage and search.
The CLI side was mirrored from the MCP path (server/tools/session.py:96-105) and faithfully inherits the same gap — fixing only one surface would leave the other open.
What we want
A single validate_agent_id(value) (or validate_name(value, kind=\"agent-id\")) hook applied at one boundary so both mm session start / mm session wrap and mem_session_start raise a clear error when the agent id contains:
: (clashes with the namespace separator)
/ .. (path-traversal-shaped values)
- leading/trailing whitespace
- zero-width or control characters
- anything beyond the existing canonical agent-name charset (look at
validate_name callers under context/_names.py as the closest precedent)
Acceptance
- Reject the cases above with a single, identical error message in both the CLI and MCP entry points.
- Regression test that pins
\"agent-runtime:foo:bar\" cannot end up in storage from either surface.
- Document the validator's accepted charset alongside
AGENT_NAMESPACE_PREFIX in constants.py.
Out of scope
- Renaming or migrating any agent ids users might already have stored — this is a forward gate only.
- Tightening the surface review G2 follow-up further ("different agent_id formats per runtime" etc.). Track separately if it comes up.
Provenance
Context
PR #485 review (item 2) flagged that
f\"{AGENT_NAMESPACE_PREFIX}{agent_id}\"does not validateagent_idbefore concatenation. Hostile-shaped values likefoo:bar,../x, or whitespace produce malformed-but-stored namespace strings ("agent-runtime:foo:bar", etc.) that round-trip into storage and search.The CLI side was mirrored from the MCP path (
server/tools/session.py:96-105) and faithfully inherits the same gap — fixing only one surface would leave the other open.What we want
A single
validate_agent_id(value)(orvalidate_name(value, kind=\"agent-id\")) hook applied at one boundary so bothmm session start/mm session wrapandmem_session_startraise a clear error when the agent id contains::(clashes with the namespace separator)/..(path-traversal-shaped values)validate_namecallers undercontext/_names.pyas the closest precedent)Acceptance
\"agent-runtime:foo:bar\"cannot end up in storage from either surface.AGENT_NAMESPACE_PREFIXinconstants.py.Out of scope
Provenance
mm session start --agent-id#485 (item 2 — "agent_id is not validated before namespace concatenation")