[bug] hero_embedder parses but discards X-Hero-Context — cross-context vector leak risk #31
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_embedder#31
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
hero_embedderparses theX-Hero-Contextheader but immediately discards it. Per-context isolation depends entirely on every caller passing the correctnamespaceparameter — a soft contract, not enforcement. A misbehaving or compromised caller can read or pollute another context's vector index.Source
crates/hero_embedder_server/src/main.rs:38-53—X-Hero-Contextis parsed.:112and:220— the parsed value is bound to_hero_contextand never read.search(query, top_k, namespace, ...),index.add,vectors.add,namespace.create— all key off thenamespacerequest parameter, which is fully caller-controlled.Why this matters
Per-context vector indices live at
~/hero/var/embedder/data/<namespace>/q<n>/rag.redb(default root fromEMBEDDER_DATA). The embedder cannot tell whether a caller is asking on behalf of the right context — it just trusts whatevernamespacearrives.Concretely:
rpc.sock(Unix socket on the same host — boundary is filesystem permissions only) can enumerate all namespaces vianamespace.listand read any of them.Proposed fix
Two layers, defense in depth:
namespacedoesn't start with<context>/prefix, or rewrite the namespace server-side as<context>/<original>and treat the request as that namespace.namespace.list/namespace.statsthat callers can only see namespaces under their own context prefix.Severity
Medium-high. Not exploitable from outside the host, but invalidates the per-context isolation claim in the sovereignty pitch.
Cross-refs
hero_indexer(separate issue, this session)hero_aibroker(no per-context awareness at all — separate issue)Spotted during docs_hero Phase 1 source-grounded read (session 52). Reconciliation memo:
memory/investigation_roadmap_reconciliation.md.