fix(security): apply UserVisibilityFilter to briefing + cortex endpoints#221
Merged
Conversation
The briefing endpoint (GET /api/v1/briefing) and related cortex endpoints bypassed UserVisibilityFilter, leaking cross-user data in multi-tenant Pro deployments. An agent could receive briefing digests and hot_context entries from other users' agents, but then fail to read those same entries via amfs_read (which correctly applies visibility filtering). This caused a broken UX where briefing promised data that read/search could not deliver, and a tenant isolation gap where compiled knowledge from other users' agents was exposed. Changes: - Add _is_agent_visible_for_entity() helper for entity-path-scoped agent visibility checks (mirrors is_entry_visible logic) - Add _filter_briefing_digests() to filter both digest-level visibility and hot_context entries within digests - Apply visibility filtering to GET /api/v1/briefing - Apply visibility filtering to GET /api/v1/cortex/status - Apply visibility filtering to GET /api/v1/cortex/digests - Handle hot_context dict shape (uses "agent" key, not provenance) without modifying amfs-internal visibility module - 19 new unit tests covering own-agent, room co-member, system agent, foreign agent, synthesized digest, and admin bypass scenarios Admin users and OSS deployments are unaffected (should_filter=False or no visibility filter present).
…-server The CI workflow only installs core, adapters, sdk-python, mcp-server, and cortex. The http-server package is not in the test matrix, so tests importing from amfs_http fail with ModuleNotFoundError. Use pytest.importorskip to gracefully skip when not available.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixesthe briefing endpoint cross-user data that
amfs_readthen couldn't access.UserVisibilityFilterto filter digests and hot_context entriesKey implementation details
_is_agent_visible_for_entity(agent_id, entity_path, user_agents, room_map)helper mirrorsis_entry_visiblelogic but works with raw IDs (no full entry object needed)_filter_briefing_digests(vis, digests)handles digest-level filtering AND hot_context entry filtering within digests{"agent": "..."}) without modifyingamfs-internal/amfs_rooms/visibility.py-- normalization is done in the HTTP handlersource_agents), keeps the digest only if user has room access to the entity_path or there are surviving hot_context entriesshould_filter=False)UserVisibilityFilterpresent)user_agents/room_mapfrom the per-request visibility filterNot in scope (follow-up)
A full endpoint audit found ~35 additional endpoints that may need visibility filtering (SSE stream, consolidation endpoints, history, traces, etc.). These are documented in the plan and will be addressed in a separate PR.