Skip to main content
Vulnerability Database/CVE-2026-104970

CVE-2026-104970: Plane Project Management Privilege Escalation

CVE-2026-104970 is a privilege escalation vulnerability in Plane open-source project management tool allowing attackers to gain unauthorized admin access through race conditions. This article covers technical details, affected versions, and fixes.

Published:

CVE-2026-104970 Overview

Plane is an open-source project management tool affected by a race condition in its instance administrator signup flow. The vulnerability resides in InstanceAdminSignUpEndpoint within apps/api/plane/license/api/views/admin.py (lines 89-117 and 173-229). The endpoint uses InstanceAdmin.objects.first() to verify whether an administrator already exists, but performs account creation without an atomic transaction, row lock, uniqueness guard, or advisory lock. Two concurrent unauthenticated requests with different email addresses can both pass the check and receive sessions with instance-admin authority. The flaw affects versions from 0.13 until 1.4.0 and is fixed in version 1.4.0.

Critical Impact

Unauthenticated attackers can race the legitimate operator during initial setup and obtain full instance administrator privileges on a Plane deployment.

Affected Products

  • Plane (makeplane/plane) versions 0.13 through versions prior to 1.4.0
  • Self-hosted Plane instances exposed during initial administrator provisioning
  • Any Plane deployment where InstanceAdminSignUpEndpoint is reachable before setup is finalized

Discovery Timeline

  • 2026-10-05 - CVE-2026-104970 published to NVD
  • 2026-10-06 - Last updated in NVD database

Technical Details for CVE-2026-104970

Vulnerability Analysis

The flaw is a Time-of-Check Time-of-Use (TOCTOU) race condition classified under [CWE-362]. The InstanceAdminSignUpEndpoint handler reads the current admin state with InstanceAdmin.objects.first(), then conditionally creates a new User row and an associated InstanceAdmin row. These two operations are not wrapped in an atomic database transaction. No row-level lock, PostgreSQL advisory lock, or uniqueness constraint enforces serial execution of the first-admin bootstrap.

When two concurrent HTTP requests arrive before either has committed its writes, both threads observe an empty admin table. Each request proceeds to create its own User and InstanceAdmin records and returns an authenticated session with instance-admin authority. The result is multiple administrators sharing unrestricted control over the same Plane instance.

Root Cause

The root cause is a missing concurrency guard around a bootstrap check. The handler trusts a non-transactional read to make an authorization decision. Without select_for_update(), transaction.atomic(), or a unique partial index on the admin table, Django's ORM allows parallel writes that both satisfy the "no admin exists" precondition.

Attack Vector

Exploitation requires network access to a Plane instance that has not yet completed administrator provisioning. An attacker sends a signup request to InstanceAdminSignUpEndpoint concurrently with the legitimate operator's request, using a different email address. Both requests succeed, and the attacker receives an admin session cookie granting full control over users, workspaces, and instance configuration.

The attack complexity is elevated because the race window is narrow and limited to the pre-provisioning phase. However, automated tooling that polls the signup endpoint during deployment can reliably win the race against a human operator.

No verified public exploit code is available. See the GitHub Security Advisory GHSA-p548-28jp-wr4p and the fix commit 7fbf14a for technical details on the patched code path.

Detection Methods for CVE-2026-104970

Indicators of Compromise

  • Multiple InstanceAdmin rows created within milliseconds of each other during initial deployment
  • Unexpected User accounts with is_instance_admin=True holding email addresses not belonging to the operator
  • Successful HTTP 200 or 201 responses from /api/instances/admins/sign-up/ originating from unfamiliar source IPs

Detection Strategies

  • Query the Plane database for SELECT COUNT(*) FROM instance_admins and alert when the count exceeds the expected number of operators
  • Review reverse proxy or web server access logs for concurrent POST requests to the instance admin signup endpoint from distinct source addresses
  • Compare the created_at timestamps of InstanceAdmin rows; sub-second deltas across different user IDs indicate a successful race

Monitoring Recommendations

  • Instrument the Plane API tier to log every call to InstanceAdminSignUpEndpoint with source IP, user-agent, and email submitted
  • Forward application and reverse proxy logs to a centralized log platform and alert on repeat POSTs to the admin signup path
  • Audit instance administrator membership on a scheduled basis and after any infrastructure change

How to Mitigate CVE-2026-104970

Immediate Actions Required

  • Upgrade Plane to version 1.4.0 or later, which introduces the concurrency guard around admin creation
  • Audit the InstanceAdmin table and remove any unauthorized administrator accounts created during the vulnerable window
  • Rotate credentials, API tokens, and session cookies for all existing administrator accounts after upgrade
  • Restrict network access to the Plane admin signup endpoint until the upgrade is applied

Patch Information

The fix is included in Plane v1.4.0 and merged through Pull Request #9332. The patch wraps the first-admin check and account creation in an atomic transaction with appropriate locking so concurrent requests cannot both pass the uniqueness check. Review the fix commit for implementation details.

Workarounds

  • Place the Plane instance behind a reverse proxy that enforces IP allow-listing on the admin signup path until initial setup completes
  • Complete initial administrator provisioning in an isolated network segment before exposing the instance to untrusted networks
  • Add a transient firewall rule blocking /api/instances/admins/sign-up/ immediately after creating the first admin account
bash
# Example nginx snippet restricting the admin signup endpoint
location = /api/instances/admins/sign-up/ {
    allow 10.0.0.0/8;
    deny all;
    proxy_pass http://plane_api_upstream;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.