Summary
Multiple Insecure Direct Object Reference (IDOR) vulnerabilities exist in the Shortcut and User Setting gRPC services, allowing any authenticated user to access or leak data belonging to other users.
CWE-639: Authorization Bypass Through User-Controlled Key
Affected Endpoints
1. GetShortcutAnalytics — Missing Ownership Check
GetShortcutAnalytics() in server/route/api/v1/shortcut_service.go (lines 250-310) fetches a shortcut by ID and returns full analytics without verifying the caller owns or has access to the shortcut.
Compare with DeleteShortcut() (line 237) which correctly checks shortcut.CreatorId != user.ID before proceeding. GetShortcutAnalytics() has no equivalent ownership check.
2. GetUserSetting — Missing Caller Verification
GetUserSetting() in server/route/api/v1/user_setting_service.go (lines 15-21) passes request.Id directly to getUserSetting() without verifying that the authenticated caller's user ID matches request.Id. Any authenticated user can read any other user's settings by supplying an arbitrary user ID.
3. UpdateUserSetting — Response Information Leak
UpdateUserSetting() in the same file (line 51) correctly performs the actual update using user.ID from the authenticated context. However, the response is built by calling getUserSetting(ctx, s.Store, request.Id) where request.Id is caller-controlled rather than the authenticated user's ID. This leaks another user's settings in the response.
4. ListShortcuts — Missing Visibility/Ownership Filter
ListShortcuts() (lines 24-43) returns all shortcuts without filtering by visibility or ownership. The FindShortcut{} query struct has no user or visibility filter applied, exposing all users' shortcuts (including private ones) to any authenticated caller.
Impact
- Confidentiality: Any authenticated user can read other users' shortcut analytics, user settings, and private shortcuts.
- Severity: High
Recommended Fix
- GetShortcutAnalytics: Add an ownership check (
shortcut.CreatorId != user.ID) matching the pattern already used in DeleteShortcut().
- GetUserSetting: Verify
request.Id == user.ID, or ignore request.Id and always use the authenticated user's ID from context.
- UpdateUserSetting: Change the response call to use
getUserSetting(ctx, s.Store, user.ID) instead of request.Id.
- ListShortcuts: Add a
CreatorId or visibility filter to FindShortcut{} so users only see their own shortcuts and public shortcuts.
Thank you for your work on Slash. Happy to answer any questions about these findings.
Summary
Multiple Insecure Direct Object Reference (IDOR) vulnerabilities exist in the Shortcut and User Setting gRPC services, allowing any authenticated user to access or leak data belonging to other users.
CWE-639: Authorization Bypass Through User-Controlled Key
Affected Endpoints
1. GetShortcutAnalytics — Missing Ownership Check
GetShortcutAnalytics()inserver/route/api/v1/shortcut_service.go(lines 250-310) fetches a shortcut by ID and returns full analytics without verifying the caller owns or has access to the shortcut.Compare with
DeleteShortcut()(line 237) which correctly checksshortcut.CreatorId != user.IDbefore proceeding.GetShortcutAnalytics()has no equivalent ownership check.2. GetUserSetting — Missing Caller Verification
GetUserSetting()inserver/route/api/v1/user_setting_service.go(lines 15-21) passesrequest.Iddirectly togetUserSetting()without verifying that the authenticated caller's user ID matchesrequest.Id. Any authenticated user can read any other user's settings by supplying an arbitrary user ID.3. UpdateUserSetting — Response Information Leak
UpdateUserSetting()in the same file (line 51) correctly performs the actual update usinguser.IDfrom the authenticated context. However, the response is built by callinggetUserSetting(ctx, s.Store, request.Id)whererequest.Idis caller-controlled rather than the authenticated user's ID. This leaks another user's settings in the response.4. ListShortcuts — Missing Visibility/Ownership Filter
ListShortcuts()(lines 24-43) returns all shortcuts without filtering by visibility or ownership. TheFindShortcut{}query struct has no user or visibility filter applied, exposing all users' shortcuts (including private ones) to any authenticated caller.Impact
Recommended Fix
shortcut.CreatorId != user.ID) matching the pattern already used inDeleteShortcut().request.Id == user.ID, or ignorerequest.Idand always use the authenticated user's ID from context.getUserSetting(ctx, s.Store, user.ID)instead ofrequest.Id.CreatorIdor visibility filter toFindShortcut{}so users only see their own shortcuts and public shortcuts.Thank you for your work on Slash. Happy to answer any questions about these findings.