CVE-2026-105632 Overview
CVE-2026-105632 is a broken access control vulnerability [CWE-284] in Plane, an open-source project management platform. Versions prior to 1.4.0 expose a GraphQL joinProject mutation that fails to validate project-level visibility. Any authenticated workspace member can invoke the mutation to add themselves to any project within the workspace, including projects configured as network=0 (secret or private). The resolver only verifies workspace-level membership and role, bypassing the per-project tenant boundary. Successful exploitation grants the attacker a full Member role with read and write access to confidential data. The issue is fixed in Plane 1.4.0.
Critical Impact
A low-privilege workspace member can join any private project in the workspace and read or modify sensitive data without invitation.
Affected Products
- Plane (makeplane/plane) all versions prior to 1.4.0
- Self-hosted Plane deployments exposing the GraphQL API
- Plane Cloud instances on vulnerable releases
Discovery Timeline
- 2026-10-05 - CVE-2026-105632 published to the National Vulnerability Database
- 2026-10-05 - Last updated in NVD database
- Fixed in release - Plane v1.4.0 published with the security fix
- Advisory published - GitHub Security Advisory GHSA-45hc-q4mw-jhxm
Technical Details for CVE-2026-105632
Vulnerability Analysis
Plane models tenant isolation at two layers: the workspace and the project. Projects carry a network attribute that determines visibility, where network=0 denotes a secret project restricted to invited members. The GraphQL joinProject mutation was designed to let workspace members opt into projects they already have permission to view. The resolver authorized the request based only on the caller's workspace membership and role, never consulting the target project's network value or invitation state. As a result, the project-level access boundary collapsed inside the workspace trust zone. An attacker who held any workspace role could enumerate project IDs and submit mutations to join them, inheriting the Member role with read and write permissions.
Root Cause
The root cause is missing authorization logic in the UserProjectInvitationsViewset and the GraphQL resolver backing joinProject. Supplied project_ids were trusted directly, so UUIDs referencing secret projects, or even projects in other workspaces, were used in ProjectMember queries without being filtered against a workspace-scoped, network-validated queryset. The code treated workspace membership as sufficient authorization for project membership, violating the principle of least privilege [CWE-284].
Attack Vector
Exploitation requires authenticated access as any workspace member and network reachability to the Plane GraphQL endpoint. The attacker submits a joinProject mutation with the UUID of a target private project. The server adds the attacker as an active ProjectMember and returns success. The attacker then reads issues, cycles, modules, documents, and attachments in that project, and can modify or delete content.
workspace_role = workspace_member.role
workspace = workspace_member.workspace
+ # Use the workspace-scoped, network-validated project IDs only.
+ # Raw project_ids may contain UUIDs from other workspaces; those are
+ # absent from the `projects` queryset and therefore bypass the SECRET
+ # network check above (GHSA-45hc-q4mw-jhxm).
+ validated_project_ids = [str(p.id) for p in projects]
+
# If the user was already part of workspace
- _ = ProjectMember.objects.filter(workspace__slug=slug, project_id__in=project_ids, member=request.user).update(
- is_active=True
- )
+ _ = ProjectMember.objects.filter(
+ workspace__slug=slug, project_id__in=validated_project_ids, member=request.user
+ ).update(is_active=True)
ProjectMember.objects.bulk_create(
[
Source: Plane commit e1ef420. The patch replaces the raw project_ids input with validated_project_ids, which contains only IDs from the projects queryset already filtered by workspace and network scope.
Detection Methods for CVE-2026-105632
Indicators of Compromise
- GraphQL requests containing the joinProject mutation originating from users who were not previously listed as invitees of the target project.
- Unexpected ProjectMember database rows created for network=0 projects, especially where the created_by and member fields reference the same low-privilege workspace user.
- Spikes in UserProjectInvitationsViewset POST traffic targeting multiple project UUIDs from a single session.
Detection Strategies
- Audit ProjectMember records created before upgrading to 1.4.0 and reconcile them against invitation history for private projects.
- Correlate web server access logs with Plane application logs to identify workspace members who gained access to secret projects without an issued invitation.
- Hunt for repeated project enumeration patterns, such as sequential or scripted mutations referencing many project UUIDs in a short window.
Monitoring Recommendations
- Alert on new ProjectMember entries where the target project has network=0 and no corresponding ProjectInvite record exists.
- Forward Plane API and database audit logs to a centralized analytics platform for retention and query across the exposure window.
- Monitor GraphQL endpoint traffic for anomalous mutation volume per authenticated session.
How to Mitigate CVE-2026-105632
Immediate Actions Required
- Upgrade all Plane deployments to version 1.4.0 or later without delay.
- Review every private (network=0) project for unexpected members and remove unauthorized ProjectMember records.
- Rotate credentials, API tokens, and any secrets stored in issues, documents, or attachments of exposed private projects.
- Notify project owners of workspaces that contained confidential data about potential unauthorized access.
Patch Information
The fix is included in Plane v1.4.0 and introduced via Pull Request #9333 and commit e1ef420. The resolver now constructs validated_project_ids from a queryset that enforces both workspace scope and project network visibility, preventing raw caller-supplied UUIDs from bypassing the SECRET project check. Full remediation details are available in GHSA-45hc-q4mw-jhxm.
Workarounds
- If immediate upgrade is not possible, restrict access to the Plane GraphQL endpoint using a reverse proxy or Web Application Firewall rule that blocks the joinProject mutation.
- Temporarily reduce workspace membership to trusted users only, since any workspace member can exploit the flaw.
- Move highly sensitive projects to a separate workspace with a limited member roster until the patch is applied.
# Example: upgrade a self-hosted Plane deployment to the patched release
git fetch --tags
git checkout v1.4.0
docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up -d
# Verify the running version
docker compose exec api python manage.py --version
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

