Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 272/272 feeds/APIs · 469/469 docs · 7/9 advisories · checked 13:48 UTC Customize Public modeDiscuss ChangeIntel on Discord

Mem0: Cross-tenant conversation leak via unescaped delimiter collision in session-scope key (_build_session_scope)

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-116575

Published

Mem0 provides persistent memory infrastructure for AI agents and applications. Prior to Python SDK 2.0.18 and TypeScript SDK 3.1.6, _build_session_scope() in mem0/memory/main.py and Memory.buildSessionScope() in the TypeScript SDK join caller-controlled user_id, agent_id, and run_id values using unescaped & and = delimiters. A caller can embed another scope component in a controlled identifier so that distinct tenant tuples produce the same session_scope key. Memory.add(), AsyncMemory.add(), and the REST POST /memories flow use that key to read and save recent raw messages, allowing cross-tenant conversation disclosure and eviction or interleaving of another tenant's history. This issue is fixed in Python SDK 2.0.18 and TypeScript SDK 3.1.6.

Source published
26 Oct 2026 20:15:01 UTC
Source modified
27 Oct 2026 14:18:25 UTC
Observed here
27 Oct 2026 15:44:06 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · 6.3 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N

euvd · EUVD-2026-110315

Published

Mem0 provides persistent memory infrastructure for AI agents and applications. Prior to Python SDK 2.0.18 and TypeScript SDK 3.1.6, _build_session_scope() in mem0/memory/main.py and Memory.buildSessionScope() in the TypeScript SDK join caller-controlled user_id, agent_id, and run_id values using unescaped & and = delimiters. A caller can embed another scope component in a controlled identifier so that distinct tenant tuples produce the same session_scope key. Memory.add(), AsyncMemory.add(), and the REST POST /memories flow use that key to read and save recent raw messages, allowing cross-tenant conversation disclosure and eviction or interleaving of another tenant's history. This issue is fixed in Python SDK 2.0.18 and TypeScript SDK 3.1.6.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: Oct 26, 2026, 8:15:01 PM

dateUpdated: Oct 27, 2026, 2:18:25 PM

Source published
Oct 26, 2026, 8:15:01 PM (timezone not stated)
Source modified
Oct 27, 2026, 2:18:25 PM (timezone not stated)
Observed here
28 Oct 2026 21:57:34 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 3.1 · 6.3 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N

nvd · CVE-2026-116575

Published

Mem0 provides persistent memory infrastructure for AI agents and applications. Prior to Python SDK 2.0.18 and TypeScript SDK 3.1.6, _build_session_scope() in mem0/memory/main.py and Memory.buildSessionScope() in the TypeScript SDK join caller-controlled user_id, agent_id, and run_id values using unescaped & and = delimiters. A caller can embed another scope component in a controlled identifier so that distinct tenant tuples produce the same session_scope key. Memory.add(), AsyncMemory.add(), and the REST POST /memories flow use that key to read and save recent raw messages, allowing cross-tenant conversation disclosure and eviction or interleaving of another tenant's history. This issue is fixed in Python SDK 2.0.18 and TypeScript SDK 3.1.6.

NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.

Source analysis status: Deferred

Weakness classifications: CWE-200 · CWE-863

Original publisher date fields

published: 2026-10-26T21:18:13.360

lastModified: 2026-10-27T16:04:22.707

Source published
26 Oct 2026 21:18:13 UTC
Source modified
27 Oct 2026 16:04:22 UTC
Observed here
28 Oct 2026 21:57:06 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · [email protected] · Secondary · 6.3 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N

osv · GHSA-5324-3w58-qpp2

Published

Summary _build_session_scope() in mem0/memory/main.py builds the conversation-history scope key used to fetch/store the last N raw messages by naively joining caller-supplied user_id/agent_id/run_id values with unescaped & and = delimiters: def _build_session_scope(filters): parts = [] for key in sorted(["user_id", "agent_id", "run_id"]): val = filters.get(key) if val: parts.append(f"{key}={val}") return "&".join(parts) _validate_and_trim_entity_id() (the only validation applied to these values) rejects only empty/whitespace-only strings — it never forbids & or =. This scope string is then used as an exact-match key against a SQLite column (storage.py: WHERE session_scope = ?) to fetch the last 10 raw messages for a given scope (main.py, Phase 0 of _add_to_vector_store, both sync and async). Impact Any caller who controls only their own run_id (or agent_id) — a very common integration shape, since apps frequently pass a client-/session-supplied identifier straight through as run_id without namespacing — can craft a value containing &user_id=<victim> (or &agent_id=<victim>) that produces a scope string byte-for-byte identical to a different tenant's real scope string. Concretely: Tenant A calls add(msgs, user_id="alice", run_id="proj-x") → scope "run_id=proj-x&user_id=alice". An attacker who can only set run_id calls add(msgs, run_id="proj-x&user_id=alice") → identical scope string. The attacker's next add() call: 1. Reads Tenant A's raw prior conversation via get_last_messages(session_scope) and splices it verbatim into the attacker's own LLM fact-extraction prompt — a direct cross-tenant confidentiality leak (conversation content, potentially including PII, credentials, etc.). 2. Writes into the same colliding row-set via save_messages(), whose eviction logic (DELETE FROM messages WHERE session_scope = ? AND id NOT IN (...)) can evict/interleave Tenant A's history — permanent cross-tenant data corruption, not just a read. Reachable via the public Memory.add() / AsyncMemory.add() API, and by extension the REST server's POST /memories endpoint (which takes run_id/agent_id straight from the request body). Reproduction from mem0.memory.main import _build_session_scope # Tenant A: real user_id + run_id scope_a = _build_session_scope({"user_id": "alice", "run_id": "proj-x"}) print(scope_a) # "run_id=proj-x&user_id=alice" # Attacker: controls only run_id, embeds a fake user_id inside it scope_c = _build_session_scope({"run_id": "proj-x&user_id=alice"}) print(scope_c) # "run_id=proj-x&user_id=alice" assert scope_a == scope_c # byte-for-byte collision A full end-to-end proof (actual add() calls, no mocking of the vulnerable functions) confirms the attacker's subsequent add() call receives the victim's raw prior message content via get_last_messages. Suggested Fix Reject & and = in _validate_and_trim_entity_id(), alongside the existing whitespace check — this is the single validation chokepoint already used by every entry point (add, search, get_all, delete_all), so the fix is centralized. Alternatively/additionally, encode each component unambiguously (percent-encode each id, or use a length-prefixed/JSON-encoded scope key) so no valid-character combination in one field can ever collide with a different partition. Also affected: TypeScript SDK (npm mem0ai) The same flaw exists in mem0-ts/src/oss/src/memory/index.ts, Memory.buildSessionScope(), which joins agent_id/run_id/user_id into the same `key=value&key=value` string with the delimiters unescaped: private buildSessionScope(filters: SearchFilters): string { const parts: string[] = []; for (const key of ["agent_id", "run_id", "user_id"].sort()) { const val = (filters as any)[key]; if (val) parts.push(`${key}=${val}`); } return parts.join("&"); } The scope string is used the same way, as an exact-match key into the messages table via SQLiteManager.getLastMessages() and saveMessages(), so the identical forge, cross-tenant read and eviction all apply. Verified against the current releases as of 2026-07-26: pip mem0ai v2.0.14 and npm mem0ai ts-v3.1.2 both still contain the unescaped join. Reporter: Abhinav Singh (GitHub: OfficialAbhinavSingh)

Source published
28 Oct 2026 21:17:08 UTC
Source modified
28 Oct 2026 21:30:05 UTC
Observed here
28 Oct 2026 21:55:29 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N

Publisher rating · MODERATE

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 30 Oct 13:48 UTC · 272 of 272 readable · 271 fully read · documentation 469/469 current