makeplane / makeplane/plane

security: analytics charts endpoint leaks cross-workspace cycle and module dates via unscoped ID lookup

Open Beginner friendly
#9,601 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

Bug Description

The advance analytics charts endpoint looks up Cycle and Module by bare ID with no workspace scope. An authenticated user in workspace A can read start_date and end_date from cycles and modules belonging to workspace B by passing foreign UUIDs in the query parameters.

Affected file

pps/api/plane/app/views/analytic/project_analytics.py:

`python
cycle = Cycle.objects.filter(id=cycle_id).first() # line 196 - no workspace filter

...

module = Module.objects.filter(id=module_id).first() # line 208 - no workspace filter
`

The endpoint is protected by @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST]) which validates the caller's membership in the requested workspace. The CycleIssue query is correctly scoped via ase_filters (which includes workspace__slug=slug), so it returns no data for foreign cycle IDs. But the bare Cycle.objects.filter(id=...) lookup succeeds for any cycle UUID in the database, and the response includes cycle.start_date and cycle.end_date directly in the chart metadata.

Failure scenario

  1. User in workspace A calls GET /workspaces/workspace-a/projects/<any_id>/advance-analytics-charts/?type=work-items&cycle_id=<UUID_from_workspace_B>.
  2. The permission check passes (user is a member of workspace A).
  3. Cycle.objects.filter(id=<UUID_from_workspace_B>).first() returns the foreign cycle object.
  4. start_date and end_date from workspace B's cycle are included in the API response.
  5. By iterating UUIDs, an attacker can enumerate cycle date ranges across all workspaces.

Fix

python cycle = Cycle.objects.filter(id=cycle_id, workspace__slug=slug).first() module = Module.objects.filter(id=module_id, workspace__slug=slug).first()

Environment

Plane develop branch (2026-08-13).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in project_analytics.py at the advance analytics charts endpoint and review the Cycle and Module lookups alongside the existing workspace-scoped filters. Reproduce the foreign-workspace UUID scenario, then verify that the response no longer exposes chart metadata from another workspace using the endpoint's relevant tests if available.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, python
Domain
backend-api-design, security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.