[WEB-7892] fix(security): scope attachment PATCH/DELETE/GET by issue_id, drop created_by overwrite (GHSA-5mxw-g5mw-3v3w)#9315
Conversation
…id, drop created_by overwrite (GHSA-5mxw-g5mw-3v3w) All three V2 issue attachment handlers (PATCH, DELETE, GET single) looked up FileAsset by (pk, workspace, project_id) only — issue_id in the URL was silently ignored. Any project member could target another user's attachment UUID using their own issue_id, and PATCH would transfer ownership via unconditional created_by = request.user. Add issue_id=issue_id to all three FileAsset.objects.get() calls so the lookup is correctly scoped to the attachment's owning issue. Remove the created_by overwrite in PATCH — created_by is set at creation time and must not be reassigned by a subsequent upload-confirm call. Co-authored-by: Plane AI <noreply@plane.so>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughIssue attachment delete, redirect, and upload-state update paths now scope ChangesIssue attachment asset scoping
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Linked to Plane Work Item(s) This comment was auto-generated by Plane |
Summary
issue_id=issue_idtoFileAsset.objects.get()in all three V2 issue attachment handlers that were missing it:patch,delete, andget(single asset path)issue_attachment.created_by = request.userfrompatch—created_byis set at creation time and must not be overwritten by the upload-confirm callSecurity context
Advisory: GHSA-5mxw-g5mw-3v3w | Severity: High | CWE-639 (Authorization Bypass Through User-Controlled Key)
The PATCH, DELETE, and GET (single) handlers looked up
FileAssetby(pk, workspace, project_id)only. Theissue_idURL parameter was silently ignored. Any project member could supply their ownissue_idin the URL while using a victim's attachment UUID aspk— the server found and operated on the attachment regardless. In PATCH,created_by = request.usertransferred ownership to the attacker, locking the original uploader out of their own file's delete right.The V1 delete handler already scoped by
issue_idcorrectly — this PR brings the V2 handlers in line with that pattern.Files changed
apps/api/plane/app/views/issue/attachment.pyTest plan
issue_id(attacker's issue, victim's asset UUID) — verify 404issue_id— verify 404issue_id— verify 404issue_id— verify 204,created_byunchangedSummary by CodeRabbit