Skip to content

[WEB-7730] fix(security): scope cascade deletes to workspace in BulkDeleteIssuesEndpoint#9270

Merged
sriramveeraghanta merged 2 commits into
previewfrom
web-7730/fix-bulk-delete-cascade
Jun 20, 2026
Merged

[WEB-7730] fix(security): scope cascade deletes to workspace in BulkDeleteIssuesEndpoint#9270
sriramveeraghanta merged 2 commits into
previewfrom
web-7730/fix-bulk-delete-cascade

Conversation

@mguptahub

@mguptahub mguptahub commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • BulkDeleteIssuesEndpoint.delete() correctly scoped the issues queryset to workspace+project, but the cascade deletes on CycleIssue and ModuleIssue used the raw issue_ids from the request
  • An attacker could pass issue IDs from another workspace to delete CycleIssue/ModuleIssue records they don't own
  • Fix: replace issue_id__in=issue_ids (raw user input) with issue__in=issues (the already-scoped queryset) in both cascade deletes

Affected advisories (Cluster H)

Changes

File Change
apps/api/plane/app/views/issue/base.py Replace issue_id__in=issue_idsissue__in=issues in CycleIssue and ModuleIssue cascade deletes

Test plan

  • Call bulk delete with issue IDs from workspace B while authenticated in workspace A — CycleIssue/ModuleIssue records from workspace B should not be deleted
  • Verify normal bulk delete still works — issues and their cycle/module memberships in the correct workspace are deleted

Summary by CodeRabbit

Summary by CodeRabbit

  • Bug Fixes
    • Fixed bulk deletion of issues so related cycle and module associations are removed using the same already-scoped workspace and project filtering, preventing leftover orphaned records.

…Endpoint

CycleIssue and ModuleIssue cascade deletes used raw issue_ids from the
request instead of the already workspace+project scoped issues queryset,
allowing cross-workspace deletion of related records.

Fixes GHSA-6cw7-h92q-p9hg and GHSA-2rr4-rp7r-32p4.
GHSA-7q7r-mrr4-2wwx (sub-issue parent reassign) covered in WEB-7727.

Co-authored-by: Plane AI <noreply@plane.so>
Copilot AI review requested due to automatic review settings June 19, 2026 11:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a3c84d17-43ce-439a-9a4c-c0142f85546c

📥 Commits

Reviewing files that changed from the base of the PR and between d4e8026 and 85ee49a.

📒 Files selected for processing (1)
  • apps/api/plane/app/views/issue/base.py
💤 Files with no reviewable changes (1)
  • apps/api/plane/app/views/issue/base.py

📝 Walkthrough

Walkthrough

In BulkDeleteIssuesEndpoint.delete, the deletion of related CycleIssue and ModuleIssue records is changed to filter by issue__in=issues (the workspace/project-scoped queryset) instead of issue_id__in=issue_ids (raw IDs from the request payload).

Changes

Bulk Issue Deletion Scoping Fix

Layer / File(s) Summary
Scoped CycleIssue and ModuleIssue deletion
apps/api/plane/app/views/issue/base.py
CycleIssue and ModuleIssue delete calls change from issue_id__in=issue_ids to issue__in=issues, tying related-record deletions to the already workspace- and project-scoped issues queryset rather than the raw request IDs.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

A rabbit once hopped through a field of IDs,
And found some unscoped ones hiding in weeds.
"Use the queryset!" she twitched her small nose,
Now cycles and modules delete with proper scope.
Tidy and safe, as every good burrow should be! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the security fix: scoping cascade deletes to workspace in BulkDeleteIssuesEndpoint, which aligns with the main change.
Description check ✅ Passed The PR description includes comprehensive context about the security vulnerability, the fix, affected advisories, and test scenarios; however, the Type of Change checkbox section from the template is not filled out.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch web-7730/fix-bulk-delete-cascade

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@makeplane

makeplane Bot commented Jun 19, 2026

Copy link
Copy Markdown

@sriramveeraghanta sriramveeraghanta merged commit ad73ca3 into preview Jun 20, 2026
4 checks passed
@sriramveeraghanta sriramveeraghanta deleted the web-7730/fix-bulk-delete-cascade branch June 20, 2026 11:11
gentslava added a commit to gentslava/plane that referenced this pull request Jun 20, 2026
…cope + workspace-name валидация + Storybook v10)

upstream makeplane#9269/makeplane#9270 (scope issue-ID/cascade-delete к workspace в bulk-эндпоинтах), makeplane#9263/makeplane#9278 (workspace name ≥1 буквенно-цифровой), makeplane#9277 (Storybook v10). Конфликт sub_issue.py разрешён объединением: eyriehq validate_sub_issues_bulk + upstream workspace__slug-scope. Наш GraphQL-шлюз уже безопасен (мутации ре-парента scope по project=p), поддержка не нужна.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gentslava added a commit to gentslava/plane that referenced this pull request Jun 20, 2026
…oss-tenant IDOR)

Шлюз аутентифицировал (mobile JWT), но не авторизовал: _project(slug, project) брал slug/project на веру → член воркспейса A мог мутировать/читать воркспейс B по slug + известным UUID. В тему апстрим-фиксов makeplane#9269/makeplane#9270 (scope bulk-эндпоинтов к workspace). Введён _member_project(info, slug, project) — резолвит проект ТОЛЬКО для активного WorkspaceMember; заменены ~47 вызовов в work_items/epics/intake + 2 inline (invites_misc/issue_extras). Старые небезопасные _project удалены (footgun). Тест test_graphql_authz: не-член заблокирован на уровне helper'а И мутации createSubIssue; corpus-guard без регрессий.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants