Skip to content

Harden chat thread_id against squatting and schema-boundary abuse - #1517

Open
daiv-agent[bot] wants to merge 1 commit into
mainfrom
fix/thread-id-squat-hardening
Open

Harden chat thread_id against squatting and schema-boundary abuse#1517
daiv-agent[bot] wants to merge 1 commit into
mainfrom
fix/thread-id-squat-hardening

Conversation

@daiv-agent

@daiv-agent daiv-agent Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Hardens the chat conversation thread-id derivation and validation against two attack/robustness vectors: a caller replaying a deterministic webhook thread id to squat another repo's conversation, and oversized thread/run ids reaching the DB as DataError-500s. Webhook thread ids are now HMAC-SHA256 keyed by a server secret (not the unsalted MD5 they replaced), the chat API rejects digest-shaped and over-long ids at the schema boundary, and the SSE stream endpoint gains a per-user rate throttle plus a bounded async Redis pool.

Key Changes:

  • codebase.utils.compute_thread_id now derives webhook thread ids via core.utils.compute_keyed_uuid (HMAC-SHA256 keyed by a server secret) instead of the unsalted generate_uuid MD5, so the id is deterministic per (repo_slug, scope, entity_iid) but not computable from those public inputs alone.
  • Added core.encryption.get_thread_id_signing_key (HKDF-SHA256-derived 32-byte key from DAIV_ENCRYPTION_KEY/DJANGO_SECRET_KEY) and core.utils.compute_keyed_uuid; slash_commands/actions/clear.py now uses compute_thread_id for its thread-id derivation.
  • Added _validate_thread_or_run_id in daiv/chat/api/views.py, applied to create_chat_completion, cancel_chat_run, and stream_run_events: rejects empty values, values over 64 chars (400 instead of DataError-500 on the CharField(64) PKs), and deterministic-digest-shaped ids (32/64-char pure hex) to block thread_id squatting.
  • Added ChatStreamRateThrottle (30/min per authenticated user) on GET /chat/stream so an unbounded open rate cannot exhaust worker threads or the async Redis pool; new tests/unit_tests/core/test_throttling.py covers the rate, per-user budget, and 429 path.
  • Bounded the async Redis pool with ASYNC_MAX_CONNECTIONS = 50 in core/redis.py (mirrors the cache pool cap, stays above DB_POOL_MAX_SIZE = 15).
  • Added SessionAdoptionError in sessions/services.py: aget_or_create_session now refuses to graft a webhook-origin run onto a pre-existing non-webhook session on the same thread id (a possible squat), while still adopting existing webhook-origin sessions.

⚠️ DAIV can make mistakes. Please review the changes and merge the MR if everything looks good.
🔗 Generated by DAIV — view sessions


💡 Instructions for the reviewer:

  • 💬 Just leave comments/reviews mentioning @daiv-agent to get DAIV to address them for you.

@daiv-agent daiv-agent Bot added the daiv Delegate issues to DAIV agent label Aug 19, 2026
@srtab srtab self-assigned this Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

daiv Delegate issues to DAIV agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant