fix(security): enforce write permission on target workspace in folder duplicate#3478
Conversation
… duplicate The folder duplicate endpoint only checked permissions on the source workspace. When a different workspaceId was provided in the request body, folders (and their entire nested structure) were created in the target workspace without verifying the user had write access to it. The workflow duplicate helper (lib/workflows/persistence/duplicate.ts) already enforces this check, but the folder duplicate route bypassed it for folder creation. Add a permission check on the target workspace when it differs from the source, requiring write or admin access before proceeding. Add tests for cross-workspace authorization scenarios. > **AI Disclosure:** This PR was authored by an AI (Claude, Anthropic). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR SummaryMedium Risk Overview Adds a new Vitest suite for the route covering unauthenticated/insufficient source access, cross-workspace denial (read/no access), and ensuring the extra permission check is skipped for same-workspace duplication. Written by Cursor Bugbot for commit 27684e0. This will update automatically on new commits. Configure here. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Greptile SummaryThis PR closes an authorization bypass where Strengths:
Concern:
Confidence Score: 4/5
Sequence DiagramsequenceDiagram
participant Client
participant Route as duplicate route
participant Perms as getUserEntityPermissions
participant DB as Database
Client->>Route: POST body with name and optional workspaceId
Route->>Route: getSession — check authentication
alt Unauthenticated
Route-->>Client: 401
end
Route->>DB: look up source folder by id
alt Folder missing
Route-->>Client: 404
end
Route->>Perms: check source workspace access
alt Read-only or no access on source
Route-->>Client: 403 Access denied
end
Note over Route: resolve targetWorkspaceId
alt targetWorkspaceId differs from source workspaceId
Route->>Perms: check target workspace access (NEW)
alt Read-only or no access on target
Route-->>Client: 403 Write or admin access required
end
end
Route->>DB: transaction — insert root folder then child folders recursively
DB-->>Route: newFolderId and folderMapping
Route->>DB: duplicate workflows for each folder in mapping
DB-->>Route: workflow stats
Route-->>Client: 201 with duplicated folder details
Last reviewed commit: 27684e0 |
Summary
The
POST /api/folders/[id]/duplicateendpoint only verified the user's permissions on the source workspace. When a differentworkspaceIdwas supplied in the request body, the entire folder tree (and its nested sub-folders) was created in the target workspace without checking that the user had write access.This is an authorization bypass: any authenticated user who can read a folder in workspace A could duplicate its entire folder structure into workspace B, even if they have no access to workspace B at all.
The companion
duplicateWorkflow()helper (lib/workflows/persistence/duplicate.ts, lines 131-139) already enforces a target-workspace permission check, so the individual workflow copies inside the duplicated tree would fail. But the folder structure itself was created unconditionally.Changes
apps/sim/app/api/folders/[id]/duplicate/route.ts— WhentargetWorkspaceIddiffers from the source folder's workspace, callgetUserEntityPermissionson the target and reject with403if the user lacks write or admin access.apps/sim/app/api/folders/[id]/duplicate/route.test.ts— New test file covering: unauthenticated rejection, read-only source access rejection, cross-workspace authorization enforcement, and same-workspace skip of the extra check.Test plan
route.test.tsin CI🤖 Generated with Claude Code