Skip to content

Scope API sessions by session key - #42460

Closed
necoweb3 wants to merge 1 commit into
NousResearch:mainfrom
necoweb3:fix/api-sessions-session-key-scope
Closed

Scope API sessions by session key#42460
necoweb3 wants to merge 1 commit into
NousResearch:mainfrom
necoweb3:fix/api-sessions-session-key-scope

Conversation

@necoweb3

@necoweb3 necoweb3 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

This records X-Hermes-Session-Key ownership for API-server session resources and enforces that owner key across the /api/sessions resource surface.

Why

X-Hermes-Session-Key is the API server's stable per-user/channel boundary for shared-key frontend deployments. The chat endpoints parsed and forwarded it to the agent, but the session resource endpoints selected sessions by session_id only. A caller with the same bearer token and a different session key could list, read, patch, delete, fork, or continue another keyed session if it knew the session_id.

Wrong-key requests now return 404 so the session's existence is not disclosed.

Changes

  • Store gateway_session_key in session model_config when creating keyed API sessions.
  • Filter GET /api/sessions by the caller's session key.
  • Enforce owner checks on:
    • GET /api/sessions/{session_id}
    • PATCH /api/sessions/{session_id}
    • DELETE /api/sessions/{session_id}
    • GET /api/sessions/{session_id}/messages
    • POST /api/sessions/{session_id}/fork
    • POST /api/sessions/{session_id}/chat
    • POST /api/sessions/{session_id}/chat/stream
  • Preserve legacy ownerless sessions while claiming ownerless sessions on first keyed chat use.
  • Add regression coverage for wrong-key list/get/messages/patch/fork/chat/stream/delete attempts.

Tests

python -m pytest tests/gateway/test_session_api.py -q --timeout-method=thread
12 passed

@liuhao1024

Copy link
Copy Markdown
Contributor

LGTM. The session-scoping logic is well-structured:

  • _session_visible_to_key correctly allows unscoped sessions (no gateway_session_key) to remain visible to all callers for backward compatibility.
  • _claim_session_owner_if_needed lazily assigns ownership on first keyed access, so existing sessions aren't broken.
  • The list endpoint filters post-query, which is simple and correct for the current data volume.
  • _parse_session_key_header reuse keeps the header parsing consistent across endpoints.

One minor note: _session_visible_to_key compares owner_key == gateway_session_key as strings. If the header value arrives with leading/trailing whitespace, the equality check will fail silently and the caller will get a 404. Consider .strip() on the parsed key. Not blocking — the header parser likely already normalizes this.

@alt-glitch alt-glitch added type/security Security vulnerability or hardening P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery area/auth Authentication, OAuth, credential pools labels Jun 9, 2026
@necoweb3
necoweb3 force-pushed the fix/api-sessions-session-key-scope branch from b86e3b5 to 9557aaa Compare June 26, 2026 16:26
@necoweb3

Copy link
Copy Markdown
Contributor Author
Rebased this PR onto current `origin/main` and reran the focused session API coverage.

Validation:

```text
python -m pytest tests/gateway/test_session_api.py -q --timeout-method=thread
13 passed

@necoweb3 necoweb3 closed this Jun 28, 2026
@necoweb3
necoweb3 deleted the fix/api-sessions-session-key-scope branch June 28, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants