# CVE-2026-44504: aegra-api — Fixed in 0.9.7

🐍 PyPI

Not in CISA KEV

# CVE-2026-44504 — aegra-api

[Fix: aegra/aegra#337](https://github.com/aegra/aegra/pull/337)

CVE-2026-44504 is a CWE-285 vulnerability in aegra-api. A fix is available for aegra-api — see the affected versions and patch details below.

Aegra: Cross-user run injection in /threads/{thread\_id}/runs (IDOR)

Also known as[GHSA-m98r-6667-4wq7](/vulnerability/GHSA-m98r-6667-4wq7)PYSEC-2026-2328

Published

May 14, 2026

Updated

Oct 28, 2026

Affected

1 pkg

Patched

1 / 1

Exploits

None indexed

Exploitation data as of Nov 3, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

## Exploitation Status

### No confirmed exploitation observed yet

-   CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
-   A successful exploit gives an attacker total control of the affected component, not partial access.
-   CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-44504.

## EPSS Exploitation Probability

[via FIRST.org ↗](https://www.first.org/epss/)

0.3%probability of exploitation in next 30 days

Lower Risk0.00%

Lower risk than most CVEs21th percentile — riskier than 21% of all scored CVEsHighest risk

0.00%0.28%0.57%0.85%0.0%0.3%Jun 26Sep 26Nov 26

Probability of exploitation in the next 30 days, from [FIRST.org EPSS](https://www.first.org/epss/).

## Real-World Exposure

1 pkg affected

🐍`aegra-api`

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

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

```
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](https://github.com/aegra/aegra/issues/336)
-   Fix PR: [https://github.com/aegra/aegra/pull/337](https://github.com/aegra/aegra/pull/337)
-   Release: [https://github.com/aegra/aegra/releases/tag/v0.9.7](https://github.com/aegra/aegra/releases/tag/v0.9.7)

## Affected Packages

1 total 1 fixed

Ecosystem

Package

Vulnerable range

Fix

🐍PyPI

`aegra-api` 

≥ 0.9.0&&< 0.9.7

0.9.7`pip install --upgrade 'aegra-api==0.9.7'`

## Detection & mitigation playbook

Open-source dependency

1.  ### Detect
    
    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for aegra-api, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
    
2.  ### Fix
    
    Update aegra-api to 0.9.7 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-44504 is resolved across your whole dependency graph.
    
3.  ### Workarounds
    
    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
    

## Frequently Asked Questions

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

O3 Security · Impact-Aware SCA

### Is CVE-2026-44504 in your dependencies?

Find it across PyPI, including transitive dependencies.

[Scan my dependencies](/book-demo) [How O3 SCA works](/impact-aware-sca)