makeplane / makeplane/plane

Completed cycles can be edited by including sort_order in the payload

Open
#9,362 1 comment 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

Completed cycles can be edited by including sort_order in the payload

What we observed

The cycle update endpoint is intended to lock completed cycles (those with an end_date in the past) so that only sort_order can be changed. However, any field — name, description, dates — can be modified as long as sort_order is included alongside the other fields in the same PATCH request.

1. Completed cycle accepts name and description changes

We created a cycle with start and end dates in the past (already completed). A PATCH request with only {"name": "new name"} was correctly rejected with 400 — "The Cycle has already been completed so it cannot be edited." But when we sent {"sort_order": 1, "name": "new name", "description": "new desc"}, the request succeeded with 200 and the cycle's name and description were both updated. We verified at the database level that the name and description had been overwritten.

Impact
  • Completed cycle data can be silently altered, undermining the integrity of historical sprint records
  • Auditing and reporting that relies on completed-cycle immutability becomes unreliable
  • Any user with write access to cycles can retroactively change cycle metadata after a sprint closes
Steps to reproduce

Environment:

  • makeplane/plane-backend:stable
  • PostgreSQL 15.7, Valkey 7.2.11, RabbitMQ 3.13.6, MinIO
  • ENABLE_EMAIL_PASSWORD=1, ENABLE_SIGNUP=1

Setup:

  1. Complete instance admin sign-up to bootstrap the Plane instance
  2. Create a workspace and project
  3. Create an API token for use with the v1 API
  4. Create a cycle with both start_date and end_date in the past (e.g., 2024-01-01 to 2024-01-14) — this makes the cycle "completed"

The cycle is created via:

POST /api/v1/workspaces/{slug}/projects/{project_id}/cycles/
X-Api-Key: {token}
Content-Type: application/json

{"name": "Sprint Alpha", "description": "Original description", "start_date": "2024-01-01", "end_date": "2024-01-14"}

Control — sort_order-only edit (should succeed):

PATCH /api/v1/workspaces/{slug}/projects/{project_id}/cycles/{cycle_id}/
X-Api-Key: {token}
Content-Type: application/json

{"sort_order": 1}

Returns 200 — sort_order is the one field that should remain editable on completed cycles.

Control — name-only edit (should be rejected):

PATCH /api/v1/workspaces/{slug}/projects/{project_id}/cycles/{cycle_id}/
X-Api-Key: {token}
Content-Type: application/json

{"name": "Attempted Change"}

Returns 400 — "The Cycle has already been completed so it cannot be edited." This confirms the guard is active.

Bug — including sort_order alongside other fields bypasses the guard:

PATCH /api/v1/workspaces/{slug}/projects/{project_id}/cycles/{cycle_id}/
X-Api-Key: {token}
Content-Type: application/json

{"sort_order": 1, "name": "HIJACKED NAME", "description": "HIJACKED DESCRIPTION"}

Returns 200. The cycle's name and description are both updated despite the cycle being completed.

Database verification:

SELECT name, description FROM cycles WHERE id = '{cycle_id}';

Returns name = 'HIJACKED NAME' and description = 'HIJACKED DESCRIPTION', confirming the data was persisted.

Reproducing with Dokkimi

Dokkimi is an open-source testing tool that stands up isolated Docker environments from declarative YAML definitions — services, databases, seed data, test steps, and assertions all in one file. The definition for this bug is in dokkimi/dokkimi-in-the-wild/.dokkimi/planedokkimi run reproduces it from scratch.

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 at the PATCH cycle update endpoint described in the reproduction steps and run the supplied Dokkimi definition in dokkimi/dokkimi-in-the-wild/.dokkimi/plane. Compare the sort_order-only, name-only, and combined payload behavior, then verify that completed cycles reject non-sort_order changes while still allowing sort_order updates.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, postgresql, python
Domain
api, backend, databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.