Skip to content

fix: enforce per-user memory/session isolation for multi-user gateway#17989

Closed
Cyrene963 wants to merge 1 commit into
NousResearch:mainfrom
Cyrene963:fix/per-user-memory-isolation
Closed

fix: enforce per-user memory/session isolation for multi-user gateway#17989
Cyrene963 wants to merge 1 commit into
NousResearch:mainfrom
Cyrene963:fix/per-user-memory-isolation

Conversation

@Cyrene963

@Cyrene963 Cyrene963 commented Apr 30, 2026

Copy link
Copy Markdown

Problem

In multi-user gateway deployments (e.g., multiple Telegram users sharing one Hermes instance), user data leaks across sessions:

1. System prompt injection — USER.md shared across all users

USER.md is a single shared file (~/.hermes/memories/USER.md). When User A's profile (name, school, DOB, goals) is in USER.md, User B sees User A's identity in their system prompt.

Fix: Per-user memory directories — memories/{chat_id}/USER.md and memories/{chat_id}/MEMORY.md.

2. session_search cross-user leakage

session_search searches the entire session database without user filtering, exposing User A's conversation history to User B or cron jobs.

Fix: Added user_id parameter to search_messages() and list_sessions_rich() in hermes_state.py, threaded through session_search_tool.py.

3. Hindsight memory cross-contamination on iLink WeChat (微信)

The iLink Bot API (ilinkai.weixin.qq.com) reports the bot's own user_id as from_user_id for ALL inbound messages, regardless of who actually sent them. This means:

  • All messages from different WeChat users share the same from_user_id
  • Hindsight stores them in the same memory bank
  • User A's memories contaminate User B's context

Fix: Per-platform retain gate in hindsight/__init__.py — skips auto_retain on platforms that can't distinguish users (detected by platform name or identical from_user_id).

Changes (5 files, +63/-25)

File Change
tools/memory_tool.py get_memory_dir(user_id=None) returns per-user subdir; MemoryStore accepts user_id
run_agent.py Pass self._user_id to MemoryStore()
tools/session_search_tool.py Thread user_id to DB queries
plugins/memory/hindsight/__init__.py Per-platform retain gate (skip on iLink/WeChat)
hermes_state.py user_id filter in search_messages() and list_sessions_rich()

How to set up per-user USER.md

mkdir -p ~/.hermes/memories/{chat_id}
echo "User profile..." > ~/.hermes/memories/{chat_id}/USER.md

Testing

  1. Start gateway with two Telegram users → verify User B doesn't see User A's profile
  2. User B calls session_search → verify only User B's sessions appear
  3. For WeChat/iLink users → verify Hindsight retains memories per contact, not globally

Related

Supersedes #12571 (original session_search + iLink fix, unmerged)

@alt-glitch alt-glitch added type/security Security vulnerability or hardening P1 High — major feature broken, no workaround comp/agent Core agent loop, run_agent.py, prompt builder comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins tool/memory Memory tool and memory providers labels Apr 30, 2026
@Cyrene963 Cyrene963 force-pushed the fix/per-user-memory-isolation branch from d6df96b to 58a4dd6 Compare May 2, 2026 15:21
Cyrene963 pushed a commit to Cyrene963/hermes-agent that referenced this pull request May 4, 2026
…ries

- Add user_id parameter to session_search(), list_sessions_rich(), search_messages()
- Add s.user_id = ? WHERE clause in both DB query methods
- Pass user_id through tool handler kwargs
- Fixes multi-user isolation regression where all users could see each other's sessions

Closes NousResearch#17989 (isolation incomplete without query-level filtering)
@Cyrene963 Cyrene963 force-pushed the fix/per-user-memory-isolation branch from 0eaa539 to d3e25da Compare May 7, 2026 13:42
- Add user_id parameter to MemoryStore and get_memory_dir() for per-user USER.md/MEMORY.md
- Pass user_id from AIAgent to MemoryStore during initialization
- Per-user memory directories: memories/{chat_id}/USER.md, memories/{chat_id}/MEMORY.md
- Adds session_search user_id filtering (from PR NousResearch#12571)
- Adds Hindsight per-platform retain gate (from PR NousResearch#12571)

Fixes cross-user data leakage where User A's profile and memory were
injected into User B's system prompt in multi-user gateway deployments.
@Cyrene963

Copy link
Copy Markdown
Author

Closing this PR — the functionality has already been implemented locally in our fork's patch stack (local patch applied). The local implementation covers the same scope and has been running in production.

Thanks for the contribution! If upstream merges similar functionality, we'll rebase our patches accordingly.

@Cyrene963 Cyrene963 closed this May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P1 High — major feature broken, no workaround tool/memory Memory tool and memory providers type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants