#14446·omi

[Bounty $200] security: slack/clickup/twitter transcript webhooks + slack tools trust client-supplied uid — unauthenticated writes into victim workspaces

Author: hridaya423Created Sep 18, 2026Updated Sep 18, 2026

Summary

Real-time transcript webhooks and chat-tool routes in three apps bind uid straight from the request with no authentication, then act on that uid's stored OAuth credentials:

  • omi-slack-app /webhook — attacker transcript segments get posted as messages into the victim's connected Slack channel. The /api/send_message, /api/search_messages, /api/search_channels chat tools take uid in the JSON body and act directly with the victim's token (send/search as them).
  • omi-clickup-app /webhook — attacker transcript segments create tasks in the victim's ClickUp list.
  • omi-twitter-app /webhook — attacker transcript segments trigger tweets from the victim's account.

Anyone who knows or guesses a uid can push arbitrary transcript content (or direct tool calls) that the victim's connected workspace acts on — unauthenticated write/spam path into third-party accounts. Same defect class as the zapier fix in #14428/#14429 and the paid mentor fix (#13685); these apps were missed by both and by the umbrella uid-as-auth PR #13463.

Fix

Each app gets the mentor-pattern guard module (<app>_webhook_auth.py): a shared-secret check (Authorization: Bearer or <app>_webhook_token query param, <APP>_WEBHOOK_SECRET env). /webhook routes bind uid via Depends(require_<app>_webhook_auth); slack's body-uid /api/* tools get require_slack_tool_auth (caller authentication only). Fail-closed 503 when unconfigured, 401 on missing/wrong token, 422 on blank uid.

Scope note: backend-invoked routes only — the pattern of the merged mentor fix. The browser-called settings routes share the fleet-wide uid model tracked by #13463.

PR with fix + tests: #14447. cc @kodjima33 @Git-on-my-level