Mahdi Salmanzade
271489a10c
fix(research): owner-scope endpoint resolution
...
POST /api/research/start (require_privilege "can_use_research" — a normal
user, not admin) resolves an endpoint two ways and feeds the row's *decrypted*
api_key + base_url into research_handler.start_research(llm_endpoint=,
llm_headers=):
1. body.endpoint_id -> query(ModelEndpoint).filter(id == endpoint_id,
is_enabled == True).first()
2. no endpoint + nothing configured -> query(ModelEndpoint).filter(
is_enabled == True).first()
Neither was owner-scoped. ModelEndpoint is a per-user resource (core/database.py:
non-null owner = private, "the model picker only shows the endpoint to that
user"). So a research-privileged user (or a chat-scoped token) could pass another
user's PRIVATE endpoint_id — or fall through to their first-enabled row — and run
research against that owner's endpoint: spending their API key / quota and
reaching whatever internal base_url they configured (SSRF).
This is the same multi-tenant owner-scoping class already fixed for
companion/models, the /api/v1/chat session gate (#870 ), and the /api/v1/chat
first-enabled fallback (#1045 , _first_enabled_endpoint). These two sinks on the
research path were missed.
Extract `_owned_enabled_endpoint(db, owner, endpoint_id=None)` which scopes via
the shared owner_filter helper (own rows + legacy null-owner shared rows),
matching webhook_routes._first_enabled_endpoint and session_routes._owned_endpoint.
Used for both sinks. A scoped miss on the explicit-id path returns the existing
404 ("Endpoint not found or disabled"), so endpoint existence isn't revealed. A
null/empty owner stays a no-op (single-user / legacy mode).
Add regression tests pinning both lookups (cross-owner rejected, own-row
allowed, legacy shared-row allowed, disabled-skipped, fallback never borrows,
null-owner no-op).
2026-06-03 23:19:28 +01:00
..
2026-05-31 23:58:26 +09:00
2026-05-31 23:58:26 +09:00
2026-06-03 13:25:26 +09:00
2026-06-03 14:23:10 +09:00
2026-06-01 14:32:41 +09:00
2026-06-03 01:47:13 +09:00
2026-06-02 20:35:57 +09:00
2026-06-02 13:06:09 +09:00
2026-06-03 14:06:39 +09:00
2026-06-03 08:56:48 +09:00
2026-06-03 00:57:20 +09:00
2026-06-03 22:47:00 +09:00
2026-06-03 08:11:37 +09:00
2026-06-02 20:28:26 +09:00
2026-06-02 20:42:32 +09:00
2026-06-02 01:32:00 +02:00
2026-06-01 02:22:17 +00:00
2026-06-03 13:34:54 +09:00
2026-06-03 14:14:16 +09:00
2026-06-03 14:23:40 +09:00
2026-06-03 14:23:40 +09:00
2026-06-03 13:37:54 +09:00
2026-06-02 06:02:49 +09:00
2026-06-03 08:38:27 +09:00
2026-06-03 13:29:14 +09:00
2026-06-03 14:07:14 +09:00
2026-06-03 14:11:45 +09:00
2026-06-03 14:23:37 +09:00
2026-06-03 08:59:16 +09:00
2026-06-02 12:40:28 +09:00
2026-06-03 02:50:02 +09:00
2026-06-03 08:35:16 +09:00
2026-06-03 01:44:02 +09:00
2026-06-03 08:57:15 +09:00
2026-06-03 14:11:17 +09:00
2026-06-02 23:14:52 +09:00
2026-06-02 20:42:37 +09:00
2026-06-03 14:14:41 +09:00
2026-06-01 13:42:44 +09:00
2026-06-03 14:24:14 +09:00
2026-06-03 02:37:45 +09:00
2026-06-03 13:37:39 +09:00
2026-06-03 14:16:58 +09:00
2026-06-03 14:16:55 +09:00
2026-06-02 20:55:30 +09:00
2026-06-02 21:00:58 +09:00
2026-06-03 14:14:34 +09:00
2026-06-02 20:52:03 +09:00
2026-06-02 20:52:08 +09:00
2026-06-01 22:33:35 +09:00
2026-06-03 08:59:49 +09:00
2026-06-01 22:22:41 +09:00
2026-06-03 14:06:57 +09:00
2026-06-02 20:42:21 +09:00
2026-06-03 14:14:27 +09:00
2026-06-03 14:23:40 +09:00
2026-06-02 13:15:22 +09:00
2026-06-03 23:17:12 +01:00
2026-06-01 22:24:27 +09:00
2026-06-03 14:23:01 +09:00
2026-06-03 14:23:34 +09:00
2026-06-03 14:11:21 +09:00
2026-06-03 14:24:04 +09:00
2026-06-03 01:36:57 +09:00
2026-06-03 14:12:14 +09:00
2026-06-03 13:25:33 +09:00
2026-06-03 14:11:56 +09:00
2026-06-03 04:26:15 +09:00
2026-06-03 14:12:17 +09:00
2026-06-03 03:48:25 +09:00
2026-06-03 00:09:48 +09:00
2026-06-03 14:24:26 +09:00
2026-06-02 22:52:37 +09:00
2026-06-03 13:23:35 +09:00
2026-06-02 12:25:56 +09:00
2026-06-03 03:00:52 +09:00
2026-06-02 11:50:03 +09:00
2026-06-03 14:23:07 +09:00
2026-06-02 20:34:25 +09:00
2026-06-03 08:11:44 +09:00
2026-06-03 04:20:48 +09:00
2026-06-02 23:52:22 +09:00
2026-06-03 13:25:41 +09:00
2026-06-02 12:41:25 +09:00
2026-06-03 01:03:58 +09:00
2026-06-03 13:28:31 +09:00
2026-06-03 14:06:46 +09:00
2026-06-03 03:31:09 +09:00
2026-06-03 13:35:01 +09:00
2026-06-03 08:59:55 +09:00
2026-06-03 01:47:13 +09:00
2026-06-02 11:48:54 +09:00
2026-06-03 13:40:19 +09:00
2026-06-03 13:28:38 +09:00
2026-06-02 20:35:27 +09:00
2026-06-03 14:23:43 +09:00
2026-06-03 13:23:01 +09:00
2026-06-02 06:00:02 +09:00
2026-06-03 14:07:03 +09:00
2026-06-03 14:24:20 +09:00
2026-06-03 14:23:58 +09:00
2026-06-03 13:28:53 +09:00
2026-06-02 23:11:04 +09:00
2026-06-02 20:28:01 +09:00
2026-06-03 02:21:02 +09:00
2026-06-03 04:13:52 +09:00
2026-06-02 13:15:06 +09:00
2026-06-02 23:28:24 +09:00
2026-06-03 14:06:31 +09:00
2026-06-03 14:12:41 +09:00
2026-06-03 02:08:09 +09:00
2026-06-02 11:10:43 +09:00
2026-06-01 14:23:22 -04:00
2026-06-02 22:34:52 +09:00
2026-06-03 08:59:36 +09:00
2026-06-02 22:35:30 +09:00
2026-06-03 14:24:30 +09:00
2026-06-03 14:24:07 +09:00
2026-06-02 20:32:56 +09:00
2026-06-03 14:14:37 +09:00
2026-06-03 14:11:24 +09:00
2026-06-03 08:36:51 +09:00
2026-06-02 20:34:05 +09:00
2026-06-03 13:34:17 +09:00
2026-06-03 14:23:04 +09:00
2026-06-01 22:35:24 +09:00
2026-06-03 13:23:08 +09:00
2026-06-03 13:45:56 +09:00
2026-06-03 22:47:00 +09:00
2026-06-03 04:05:40 +09:00
2026-06-03 00:30:03 +09:00
2026-06-03 13:30:11 +09:00
2026-06-03 14:22:51 +09:00
2026-06-02 11:36:01 +09:00
2026-06-02 21:01:42 +09:00
2026-06-03 14:11:10 +09:00
2026-06-01 22:47:47 +09:00
2026-06-02 23:12:34 +09:00
2026-06-03 14:22:42 +09:00
2026-06-03 14:23:30 +09:00
2026-06-02 13:07:20 +09:00
2026-06-03 03:19:39 +09:00
2026-06-02 22:36:12 +09:00
2026-06-02 23:02:28 +09:00
2026-06-03 14:22:49 +09:00
2026-06-03 09:00:04 +09:00
2026-06-03 14:07:11 +09:00
2026-06-03 13:24:24 +09:00
2026-06-03 13:24:33 +09:00
2026-06-02 11:12:54 +09:00
2026-06-03 13:29:21 +09:00
2026-06-02 11:14:31 +09:00
2026-06-03 13:29:36 +09:00
2026-06-02 05:54:23 +09:00
2026-06-03 13:33:50 +09:00
2026-06-02 20:27:24 +09:00
2026-06-03 01:41:24 +09:00
2026-06-02 11:48:17 +09:00
2026-06-03 14:12:17 +09:00
2026-06-03 13:37:14 +09:00
2026-06-02 11:39:40 +09:00
2026-06-03 22:47:00 +09:00
2026-06-03 13:36:57 +09:00
2026-06-02 23:04:58 +09:00
2026-06-02 23:01:04 +09:00
2026-06-02 20:36:54 +09:00
2026-06-02 11:47:58 +09:00
2026-06-03 08:59:30 +09:00
2026-06-03 13:31:10 +09:00
2026-06-03 08:57:23 +09:00
2026-06-03 01:53:47 +09:00
2026-06-03 01:59:05 +09:00
2026-06-03 14:17:02 +09:00
2026-06-03 09:00:10 +09:00
2026-06-02 11:28:52 +09:00
2026-06-03 00:49:29 +09:00
2026-06-03 08:35:09 +09:00
2026-06-03 14:11:35 +09:00
2026-06-03 08:35:54 +09:00
2026-06-03 13:45:33 +09:00
2026-06-02 11:50:17 +09:00
2026-06-03 03:46:07 +09:00
2026-06-03 13:41:46 +09:00
2026-06-03 14:11:42 +09:00
2026-06-03 13:25:48 +09:00
2026-06-03 14:07:00 +09:00
2026-06-02 11:27:31 +09:00
2026-06-03 13:35:09 +09:00
2026-06-03 23:13:56 +01:00
2026-06-03 13:38:02 +09:00
2026-06-03 14:11:49 +09:00
2026-06-02 23:31:09 +09:00
2026-06-02 20:33:09 +09:00
2026-06-03 14:11:31 +09:00
2026-06-03 22:47:00 +09:00
2026-06-03 14:16:52 +09:00
2026-06-03 04:07:31 +09:00
2026-06-02 21:00:50 +09:00
2026-06-03 14:11:53 +09:00
2026-06-02 20:51:16 +09:00
2026-06-03 22:47:00 +09:00
2026-06-03 08:56:56 +09:00
2026-06-02 11:41:33 +09:00
2026-06-02 12:24:18 +09:00
2026-06-03 08:57:47 +09:00
2026-06-03 01:20:43 +09:00
2026-06-01 18:27:17 +09:00
2026-06-03 14:06:42 +09:00
2026-06-03 13:29:57 +09:00
2026-06-02 20:35:44 +09:00
2026-06-03 13:42:05 +09:00
2026-06-03 08:37:29 +09:00
2026-06-02 11:28:52 +09:00
2026-06-01 22:33:35 +09:00
2026-06-03 04:02:16 +09:00
2026-06-01 22:36:53 +09:00
2026-06-02 20:45:48 +09:00
2026-06-03 14:12:45 +09:00
2026-06-03 13:23:50 +09:00
2026-06-03 08:57:35 +09:00
2026-06-03 14:10:58 +09:00
2026-06-03 03:59:05 +09:00
2026-06-02 20:32:08 +09:00
2026-06-03 04:09:28 +09:00
2026-06-03 14:12:31 +09:00
2026-06-02 20:42:43 +09:00
2026-06-02 11:11:17 +09:00
2026-06-02 12:53:50 +09:00
2026-06-03 14:23:21 +09:00
2026-06-03 14:11:14 +09:00
2026-06-03 01:10:06 +09:00
2026-06-03 13:31:33 +09:00
2026-06-03 13:29:51 +09:00
2026-06-03 08:36:45 +09:00
2026-06-02 22:42:23 +09:00
2026-05-31 23:58:26 +09:00
2026-06-02 23:33:22 +09:00
2026-06-03 03:42:01 +09:00
2026-06-02 23:18:15 +09:00
2026-06-03 13:34:47 +09:00
2026-06-03 13:37:22 +09:00
2026-06-02 11:42:20 +09:00
2026-06-03 02:32:38 +09:00
2026-06-03 08:36:57 +09:00
2026-06-03 14:12:38 +09:00
2026-06-03 23:19:28 +01:00
2026-06-03 13:29:29 +09:00
2026-06-03 13:34:40 +09:00
2026-06-02 20:42:15 +09:00
2026-06-02 22:51:25 +09:00
2026-06-02 11:30:53 +09:00
2026-06-03 03:24:09 +09:00
2026-06-03 08:57:09 +09:00
2026-06-01 23:25:38 +01:00
2026-06-03 13:42:24 +09:00
2026-06-01 22:26:37 +09:00
2026-06-02 05:58:58 +09:00
2026-06-02 12:24:50 +09:00
2026-06-03 13:34:33 +09:00
2026-06-02 20:37:14 +09:00
2026-06-03 13:31:19 +09:00
2026-06-03 01:21:57 +09:00
2026-06-03 13:44:18 +09:00
2026-06-03 14:14:30 +09:00
2026-06-03 14:12:07 +09:00
2026-06-03 00:26:37 +09:00
2026-06-02 10:53:33 +09:00
2026-06-03 13:24:17 +09:00
2026-06-02 23:37:15 +09:00
2026-06-03 14:22:55 +09:00
2026-06-02 20:53:07 +09:00
2026-06-02 21:02:26 +09:00
2026-06-03 14:24:23 +09:00
2026-06-03 13:30:28 +09:00
2026-06-03 08:36:01 +09:00
2026-06-01 23:09:41 +09:00
2026-06-03 22:47:00 +09:00
2026-06-03 14:23:52 +09:00
2026-06-03 22:47:00 +09:00
2026-06-03 13:30:19 +09:00
2026-06-03 13:33:56 +09:00
2026-06-03 03:56:54 +09:00
2026-06-03 14:12:17 +09:00
2026-06-02 23:09:15 +09:00
2026-06-03 13:22:52 +09:00
2026-06-02 12:34:42 +09:00
2026-06-02 21:02:26 +09:00
2026-06-03 14:22:58 +09:00
2026-06-03 13:45:07 +09:00
2026-06-03 02:40:22 +09:00
2026-06-03 08:35:47 +09:00
2026-06-02 20:51:26 +09:00
2026-06-03 14:24:01 +09:00
2026-06-01 16:55:09 +09:00
2026-06-02 11:39:01 +09:00
2026-06-03 08:57:41 +09:00
2026-06-03 14:23:27 +09:00
2026-06-03 14:11:05 +09:00
2026-06-03 03:53:05 +09:00
2026-06-01 22:38:56 +09:00
2026-06-02 23:20:00 +09:00
2026-06-03 13:37:46 +09:00
2026-06-03 14:10:54 +09:00
2026-06-03 14:16:48 +09:00
2026-06-03 13:22:46 +09:00
2026-06-03 14:06:53 +09:00
2026-06-02 11:15:45 +09:00
2026-06-03 03:16:11 +09:00
2026-06-03 08:37:05 +09:00
2026-06-03 14:11:38 +09:00
2026-06-02 20:28:36 +09:00
2026-06-03 02:27:43 +09:00
2026-06-03 08:59:24 +09:00
2026-06-03 00:42:56 +09:00
2026-06-03 14:24:11 +09:00
2026-06-03 13:34:25 +09:00
2026-06-02 10:44:39 +09:00
2026-06-03 08:57:54 +09:00
2026-06-02 20:36:13 +09:00
2026-06-03 14:11:02 +09:00
2026-06-03 14:23:15 +09:00
2026-06-02 20:36:37 +09:00
2026-06-02 20:43:24 +09:00
2026-06-02 20:51:21 +09:00
2026-06-03 14:23:40 +09:00
2026-06-03 14:06:49 +09:00
2026-06-03 13:31:26 +09:00
2026-06-03 14:12:35 +09:00
2026-06-02 20:32:20 +09:00
2026-06-03 08:59:42 +09:00
2026-06-02 23:13:30 +09:00
2026-06-03 13:33:43 +09:00
2026-06-02 23:22:57 +09:00
2026-06-02 20:44:27 +09:00
2026-06-03 01:26:47 +09:00
2026-06-02 20:43:29 +09:00
2026-06-03 14:12:03 +09:00
2026-06-03 13:24:00 +09:00
2026-06-02 12:57:45 +09:00
2026-06-03 08:57:03 +09:00
2026-06-03 04:12:23 +09:00
2026-06-03 00:59:01 +09:00
2026-06-03 13:28:45 +09:00
2026-06-03 01:16:30 +09:00
2026-06-03 04:04:19 +09:00
2026-06-02 20:42:26 +09:00
2026-06-02 23:46:33 +09:00
2026-06-03 02:13:51 +09:00
2026-06-02 23:03:46 +09:00
2026-06-03 04:17:40 +09:00
2026-06-03 14:22:45 +09:00
2026-06-03 14:06:35 +09:00
2026-06-01 22:26:13 +09:00
2026-06-03 14:11:28 +09:00
2026-06-03 14:14:23 +09:00
2026-06-02 11:23:40 +09:00
2026-06-02 20:45:32 +09:00
2026-06-02 20:44:24 +09:00
2026-06-03 13:38:11 +09:00
2026-06-03 13:29:01 +09:00
2026-06-03 13:29:08 +09:00