CVE-2026-44504

GHSA-m98r-6667-4wq7 HIGH
Published May 7, 2026

## 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...

Full CISO analysis pending enrichment.

Affected Systems

Package Ecosystem Vulnerable Range Patched
aegra-api pip >= 0.9.0, < 0.9.7 0.9.7
31.1K 3.1K dependents Pushed 4d ago 100% patched ~3d to patch Full package profile →

Do you use aegra-api? You're affected.

Severity & Risk

CVSS 3.1
N/A
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
N/A

Recommended Action

Patch available

Update aegra-api to version 0.9.7

Compliance Impact

Compliance analysis pending. Sign in for full compliance mapping when available.

Frequently Asked Questions

What is CVE-2026-44504?

Aegra has cross-user run injection in /threads/{thread_id}/runs (IDOR)

Is CVE-2026-44504 actively exploited?

No confirmed active exploitation of CVE-2026-44504 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-44504?

Update to patched version: aegra-api 0.9.7.

What is the CVSS score for CVE-2026-44504?

No CVSS score has been assigned yet.

Technical Details

NVD Description

## 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 before allowing the operation. Without a handler, no built-in authorization runs on these write paths. Example mitigation handler: ```python from langgraph_sdk import Auth auth = Auth() @auth.on("threads", "create_run") async def enforce_thread_owner(ctx: Auth.types.AuthContext, value: dict): # Look up the thread, raise 404 if not owned by ctx.user.identity. # Implementation depends on your data layer. ... ``` ## Root cause Aegra's authorization model delegates per-resource policy to user-defined `@auth.on` handlers. When no handler is registered, `handle_event(...)` returns `None` and the request proceeds (default-allow). Read endpoints in `api/threads.py` add a defense-in-depth `user_id` filter at the SQL layer, but the run-creation endpoints in `api/runs.py` skipped that filter. Result: out-of-the-box deployments without custom auth handlers were vulnerable. ## Affected endpoints - `POST /threads/{thread_id}/runs` - `POST /threads/{thread_id}/runs/stream` - `POST /threads/{thread_id}/runs/wait` Stateless variants (`POST /runs`, `POST /runs/wait`, `POST /runs/stream`) are NOT affected — they generate a fresh `thread_id` server-side and never accept a caller-supplied one. ## Credits - @JoJoTheBizarre — discovered and reported the vulnerability with a precise reproducer (#336) - @victorjmarin and @jawhardjebbi — wrote the fix and added test coverage at unit, integration, and manual-auth e2e levels (#337) ## Resources - Issue: https://github.com/aegra/aegra/issues/336 - Fix PR: https://github.com/aegra/aegra/pull/337 - Release: https://github.com/aegra/aegra/releases/tag/v0.9.7

Timeline

Published
May 7, 2026
Last Modified
May 7, 2026
First Seen
May 7, 2026

Related Vulnerabilities