Aegra has cross-user run injection in /threads/{thread_id}/runs (IDOR)
Date: 2026-05
Affected: pip/aegra-api
Attack vector: auth-bypass
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-44504
CWE: CWE-285
CWE-639

## Impact Aegra deployments running 0.9.0 through 0.9.6 with multiple authenticated users on a shared instance are vulnerable to a cross-tenant IDOR. Any authenticated user (User A), given another user's `thread_id` (User B), can: - Execute graph runs against User B's thread via `POST /threads/{thread_id}/runs`, `POST /threads/{thread_id}/runs/stream`, or `POST /threads/{thread_id}/runs/wait` - Read User B's full checkpoint state via the resulting run's `output` field - Inject arbitrary messages into User B's conversation history (persisted in B's checkpoint) - Hide their activity from User B's `GET /threads/{thread_id}/runs` listing because the run carries A's `user_id` The streaming variant is worse — the first SSE `event: values` frame returns the entire prior `messages` array immediately on connection, no graph execution needed. Thread IDs are UUIDs but leak through frontend URLs, server logs, observability traces, and shared links. Guessing is not required. ## Patches Fixed in **0.9.7**. The three affected endpoints now perform an SQL-level `user_id == authenticated_user.identity` check before calling `_prepare_run`. When the thread exists but is owned by another user, the response is `404 Thread not found` (matching the read-side pattern) to avoid leaking thread existence. ## Workarounds If upgrade is not immediately possible, register an `@auth.on("threads", "create_run")` handler that explicitly verifies thread ownership against the authenticated identity befo


Mitigations:

Architectural layers (MAESTRO):