22 Commits

Author SHA1 Message Date
Classic298 ec0e60033b perf: use the orjson codec for the permission deep copy (#27807)
`get_permissions` deep-copies the default permission tree with a `json.loads(json.dumps(...))` round trip before merging group permissions into it. It runs on signin, signup, the permissions endpoint, OAuth, and the chat-completion middleware.

It now goes through `JSONCodec`, which selects orjson when `ENABLE_ORJSON` is set. The intermediate string never leaves the expression, so neither the escaping nor the separator differences between the two backends are observable; only the resulting object is used.

`default_permissions` always originates from `Config.get('user.permissions')`, a SQLAlchemy `JSON` column, so the tree is JSON-native by construction and the round trip is exact.

Note for anyone tempted to simplify this to `copy.deepcopy`: measured on the real `DEFAULT_USER_PERMISSIONS` shape over 200k iterations, `deepcopy` takes 3.51s against 1.45s for the stdlib round trip and 0.40s for orjson. The round trip is the fast option, not a workaround.

With `ENABLE_ORJSON` unset, which is the default, `JSONCodec` is stdlib `json` and this call site behaves exactly as before.
2026-07-31 17:32:14 -04:00
G30 867006acce fix: keep admin access to connections without access grants when admin bypass is disabled (#27581) 2026-07-27 03:39:40 -04:00
Timothy Jaeryang Baek 20647bd2d5 chore: format 2026-07-27 00:12:47 -04:00
Timothy Jaeryang Baek 1f0dc90abe refac 2026-07-26 18:06:03 -04:00
Classic298 fe4b319428 fix: deny chained access to unregistered base models for non-admins (#26905)
A workspace model shared publicly could be used by any user even when its
base model was private. Unregistered base models (no row in the model
table) are admin-only for direct use — get_filtered_models hides them from
non-admins and check_model_access rejects them — but has_base_model_access
treated a missing row as "no ACL" and allowed the chained request through.

has_base_model_access now takes the caller's role and only allows an
unregistered base model hop for admins, so a shared preset can no longer
reach a base model the caller could not use directly. Registered base
models keep their existing grant-based enforcement.


Claude-Session: https://claude.ai/code/session_018toPfJW1hMXAhokGaL43Ep

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-24 01:32:32 -05:00
Timothy Jaeryang Baek 49e57f4e7e chore: format 2026-07-20 22:11:42 -04:00
Timothy Jaeryang Baek 4ed19d504b refac 2026-07-14 00:42:57 -04:00
Timothy Jaeryang Baek 5cdcdbaeec refac 2026-06-17 02:52:35 +02:00
Classic298 920b655f46 Gate scheduled automations and fail closed on per-model access for non-user roles (#26047)
Two lifecycle/authorization gaps let a deactivated (pending) account keep acting:

1. The background automation scheduler (execute_automation) rehydrated the owner by ID and
   dispatched the chat pipeline without re-checking the owner. A user later set to pending,
   or one whose features.automations permission was revoked, kept running scheduled
   automations on the operator's provider credentials, even though the HTTP create/update/run
   routes already gate on get_verified_user + features.automations. Re-gate the rehydrated
   owner before dispatch: require role user/admin and, for non-admins, the features.automations
   permission; otherwise record an error and skip the run.

2. check_model_access enforced per-model ACLs only for exactly role == 'user', so any other
   non-admin role (a pending principal) fell through and was granted access. Enforce for every
   non-admin role (admins still bypass), so the check fails closed (CWE-862, CWE-863).

Co-authored-by: rexpository <30176934+rexpository@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 22:45:27 +02:00
Timothy Jaeryang Baek 6d0295588e refac: modernize type annotations (PEP 604 / PEP 585) 2026-05-12 17:10:15 +09:00
Timothy Jaeryang Baek 1413ce4a52 refac 2026-05-12 05:30:25 +09:00
Timothy Jaeryang Baek 4113b15a60 chore: format 2026-04-17 14:28:18 +09:00
Timothy Jaeryang Baek 8acce144f9 refac 2026-04-17 14:15:36 +09:00
Timothy Jaeryang Baek 50363ba66b refac 2026-04-17 13:52:11 +09:00
Timothy Jaeryang Baek 27169124f2 refac: async db 2026-04-12 14:22:11 -05:00
Classic298 e790e7be7a fix: enforce model access control on /responses endpoint (#23481)
The /responses proxy endpoint only required authentication via
get_verified_user but did not check per-model access grants. This
allowed any authenticated user to access any model through this
endpoint, bypassing the access control system.

Extract a shared check_model_access helper into utils/access_control
and replace all inline access control blocks across openai.py and
ollama.py (7 locations) with calls to this helper. This eliminates
code duplication and prevents future policy drift between endpoints.

CWE-862: Missing Authorization
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:H (6.5 Medium)
2026-04-12 11:06:33 -05:00
Timothy Jaeryang Baek f7e07f3ca1 chore: format 2026-03-24 06:07:20 -05:00
Timothy Jaeryang Baek 945275faae refac 2026-03-22 06:58:58 -05:00
Timothy Jaeryang Baek de3317e26b refac 2026-03-17 17:58:01 -05:00
Shamil 3a6b5ebb5f refac: modernize type hints and imports in access_control module (#22594) 2026-03-11 15:28:39 -05:00
Timothy Jaeryang Baek 2751a0f0b6 refac 2026-03-01 19:09:10 -06:00
Timothy Jaeryang Baek 259d5ca596 refac 2026-03-01 13:49:36 -06:00