security: fail closed on tenant-scoped memory reads (bounty #1852) - #1891
security: fail closed on tenant-scoped memory reads (bounty #1852)#1891laurentketterle-hub wants to merge 1 commit into
Conversation
…ai#1852) MemoryReadService._get_search_namespaces() and generate_answer() silently fanned out across every namespace on the server account (list_namespaces() / namespaces[0]) when an agent_id was missing or empty. A single omitted agent_id therefore turned an agent-scoped read into a cross-tenant read of every other tenant's memories — a data isolation failure against the moorcheh-ai#1852 threat model. Fail closed instead: both paths now require an explicit agent_id and raise MemoryError otherwise. Adds regression tests covering the all-namespaces fallback and the first-namespace answer fallback. Signed-off-by: laurentketterle-hub <laurentketterle-hub@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughMemory reads now require a non-empty ChangesTenant isolation
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change makes tenant-scoped reads fail closed when no agent ID is provided, preventing unintended cross-tenant lookup behavior; no actionable merge-blocking risk remains after normal checks and review. Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Fixes a cross-tenant data isolation failure in the
memantocore read service, submitted for the Memanto Security Challenge (#1852).MemoryReadServiceexposes two entry points whose default behaviour is to drop tenant scope and fan out across every namespace on the server's Moorcheh account when anagent_idis missing or empty:_get_search_namespaces(agent_id=None)->list_namespaces()-> searches allmemanto_agent_*namespaces (used bysearch_memories/ temporal recall / recent recall).generate_answer(query, agent_id=None)->namespaces[0]-> answers from the first namespace in the account list.Both
agent_idparameters default toNone, so a single omitted argument (the default value) silently escalates an agent-scoped read into a read of every other tenant's memories — the exact "cross-tenant data leak" class this challenge asks us to find.Threat model fit
agent_idcan retrieve memories belonging to other agents/tenants sharing the same server account.Reproduction (PoC)
Fix
Fail closed instead of fail open. Both paths now require an explicit, non-empty
agent_idand raiseMemoryErrorotherwise, so a read can never silently expand beyond the caller's own namespace.Changes
memanto/app/services/memory_read_service.py:_get_search_namespacesandgenerate_answernow require anagent_id(nolist_namespaces()/namespaces[0]fallback).tests/test_memory_read_tenant_isolation.py: regression tests covering the all-namespaces fan-out and the first-namespace answer fallback.Verification
pytest tests/test_memory_read_tenant_isolation.py-> 4 passedpytest tests/(excluding network e2e/api) -> all green, no regressionsCloses the data-isolation gap described in #1852.
Summary by CodeRabbit
Bug Fixes
Tests