Skip to content

fix(memory): return HTTP 403 for cross-agent scope mismatch#737

Open
jdjioe5-cpu wants to merge 1 commit into
moorcheh-ai:mainfrom
jdjioe5-cpu:fix/cross-agent-403-guard
Open

fix(memory): return HTTP 403 for cross-agent scope mismatch#737
jdjioe5-cpu wants to merge 1 commit into
moorcheh-ai:mainfrom
jdjioe5-cpu:fix/cross-agent-403-guard

Conversation

@jdjioe5-cpu

@jdjioe5-cpu jdjioe5-cpu commented Jun 14, 2026

Copy link
Copy Markdown

Summary

The session-scope guard in every agent-scoped endpoint mapped cross-agent
access (session.agent_id != URL agent_id) to a generic Exception,
which the global error mapper then converted to HTTP 500. That is
semantically wrong: an authorization failure must be 403, not 500.

Replace all 12 occurrences with a direct HTTPException(status_code=403, ...).

Why now

Endpoints touched

remember, batch_remember, upload_file, recall, answer,
generate_daily_summary, generate_conflict_report, list_conflicts,
resolve_conflict, recall_as_of, recall_changed_since,
recall_recent.

Diff

     if session.agent_id != agent_id:
-        raise map_error_to_http_exception(
-            Exception(
-                f"Session is for agent '{session.agent_id}', cannot access '{agent_id}'"
-            )
+        raise HTTPException(
+            status_code=403,
+            detail=f"Session is for agent '{session.agent_id}', cannot access '{agent_id}'",
         )
  • 1 file changed, 36 insertions(+), 48 deletions(-)
  • All 12 sites are identical pattern replacements, no behavior change
    beyond the status code.

Validation

  • python -m ruff check memanto/app/routes/memory.py → clean
  • Existing tests that asserted status_code == 500 for an unrelated
    code path (test_create_agent_fails_when_server_key_missing) are not
    affected (different route, different failure mode).
  • No existing test asserts 500 for any cross-agent check (confirmed by
    grep over tests/).

Related

Refs PR #733, PR #736

Summary by CodeRabbit

  • Bug Fixes
    • Standardized session authorization error handling across memory operations to ensure consistent and secure access control.

The session-scope guard in every agent-scoped endpoint mapped
cross-agent access (session.agent_id != URL agent_id) to a generic
Exception, which the global error mapper then converted to HTTP 500.
That is semantically wrong: an authorization failure must be 403, not 500.

Replace all 12 occurrences of

    raise map_error_to_http_exception(
        Exception(
            f"Session is for agent '{session.agent_id}', cannot access '{agent_id}'"
        )
    )

with

    raise HTTPException(
        status_code=403,
        detail=f"Session is for agent '{session.agent_id}', cannot access '{agent_id}'",
    )

Endpoints affected: remember, batch_remember, upload_file, recall,
answer, generate_daily_summary, generate_conflict_report, list_conflicts,
resolve_conflict, recall_as_of, recall_changed_since, recall_recent.

This fixes the CodeRabbit review item flagged on PR moorcheh-ai#732's forget-endpoint
follow-up (PR moorcheh-ai#733) and the parallel review item on PR moorcheh-ai#633's edit-endpoint
follow-up (PR moorcheh-ai#736). No new tests in this commit; the test coverage lives
in those follow-up PRs so the test/fix split stays visible.
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

In memanto/app/routes/memory.py, the agent-id session mismatch error path across twelve memory endpoints is changed from calling map_error_to_http_exception(Exception(...)) to raising HTTPException(status_code=403, detail=...) directly, with an explicit mismatch message.

Changes

Session Scope 403 Enforcement

Layer / File(s) Summary
Direct 403 raise across all memory endpoints
memanto/app/routes/memory.py
In remember, batch_remember, upload_file, recall, answer, generate_daily_summary, generate_conflict_report, list_conflicts, resolve_conflict, recall_as_of, recall_changed_since, and recall_recent, the agent-id session mismatch branch replaces map_error_to_http_exception(Exception(...)) with raise HTTPException(status_code=403, detail=<explicit mismatch string>).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Poem

🐇 A mismatch of agents? No need to detour!
The 403 hops straight to the door.
No wrapping, no mapping, just raise it and say,
"This session is yours, not theirs — hop away!"
Clean paths for the warren, each endpoint secure. 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: replacing generic exception handling with HTTP 403 responses for cross-agent scope mismatches in memory endpoints.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
memanto/app/routes/memory.py (1)

150-152: ⚡ Quick win

Consider extracting agent-id scope validation into a helper.

The same 4-line agent_id mismatch check is repeated across 12 endpoints. Extracting to a reusable helper would reduce duplication and centralize the error message format.

♻️ Example helper extraction

Add to memanto/app/routes/auth_deps.py or a new memanto/app/routes/scope_validation.py:

def validate_session_scope(session: Session, agent_id: str) -> None:
    """Enforce that session.agent_id matches the requested agent_id."""
    if session.agent_id != agent_id:
        raise HTTPException(
            status_code=403,
            detail=f"Session is for agent '{session.agent_id}', cannot access '{agent_id}'",
        )

Then replace each check with:

-    if session.agent_id != agent_id:
-        raise HTTPException(
-            status_code=403,
-            detail=f"Session is for agent '{session.agent_id}', cannot access '{agent_id}'",
-        )
+    validate_session_scope(session, agent_id)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@memanto/app/routes/memory.py` around lines 150 - 152, Extract the repeated
agent_id scope validation check (comparing session.agent_id against the
requested agent_id and raising HTTPException with status_code 403) into a
reusable helper function called validate_session_scope that accepts a Session
object and agent_id string parameter. Create this helper in
memanto/app/routes/auth_deps.py or a new memanto/app/routes/scope_validation.py
file, then replace all 12 occurrences of the 4-line validation block across the
endpoints (including the one at the specified location) with a single call to
this helper function. This centralizes the error message format and eliminates
code duplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@memanto/app/routes/memory.py`:
- Around line 150-152: Extract the repeated agent_id scope validation check
(comparing session.agent_id against the requested agent_id and raising
HTTPException with status_code 403) into a reusable helper function called
validate_session_scope that accepts a Session object and agent_id string
parameter. Create this helper in memanto/app/routes/auth_deps.py or a new
memanto/app/routes/scope_validation.py file, then replace all 12 occurrences of
the 4-line validation block across the endpoints (including the one at the
specified location) with a single call to this helper function. This centralizes
the error message format and eliminates code duplication.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7d040b40-aee0-4da6-ab5e-d3cbc91e897b

📥 Commits

Reviewing files that changed from the base of the PR and between 262db90 and 6d6f83e.

📒 Files selected for processing (1)
  • memanto/app/routes/memory.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant