CVE-2026-104963
Executive Summary
CVE-2026-104963 is a broken access control (authorization) vulnerability in Plane, an open-source project management tool, affecting versions prior to 1.4.0. The WorkspaceCyclesEndpoint and WorkspaceModulesEndpoint REST resources return cycle and module records from every project in a workspace without verifying that the requester is a member of each individual project. Any authenticated workspace member — including a Guest scoped to a single project — can read cycle and module metadata belonging to private projects. The issue is fixed in 1.4.0.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
Plane organizes work hierarchically: a workspace contains projects, and each project contains cycles (sprints) and modules. Access control is expected to be enforced per project, so that a user only sees records from projects they are a member of. The sibling endpoints WorkspaceLabelsEndpoint and WorkspaceStatesEndpoint correctly constrain their querysets using the filter project__project_projectmember__member=request.user, which restricts returned rows to projects in which the requesting user holds a project membership.
WorkspaceCyclesEndpoint (served at GET /api/workspaces/{slug}/cycles/) and WorkspaceModulesEndpoint (served at GET /api/workspaces/{slug}/modules/) omit this equivalent per-project membership constraint. As a result, the queryset resolves against the whole workspace rather than against the intersection of the workspace and the requester's project memberships. This is a classic object-level authorization failure, mapped to CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor) and consistent with an IDOR/BOLA-style access control gap in the API layer.
The exposed fields include cycle and module names, descriptions, sprint dates, issue counts, progress snapshots, external integration IDs, linked URLs, and member lists. The slug workspace path parameter is required, but the flaw is not a slug-guessing problem: any authenticated member of the workspace who knows or can derive the workspace slug can invoke the endpoints, and the filtering gap causes private-project records to be returned alongside the caller's own. The inconsistency with the label/state endpoints is the key code-level signal — identical architectural intent was implemented correctly in two siblings and incorrectly in the two affected endpoints.
The attack surface is the authenticated REST API over HTTP/HTTPS. No user interaction is required, the attack is network-reachable, and complexity is low. CVSS v3.1 rates this AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N for a base score of 4.3 — the low availability and integrity impact reflects a read-only disclosure; the Low confidentiality subscore reflects the fact that only metadata and member lists (not, per the description, credentials or bulk private content) are exposed.
Exploitation Scenarios
No public PoC or exploit code is available for this CVE. The following chain is inferred strictly from the vulnerability class (broken object-level authorization) and the endpoint behavior described in the NVD entry.
Reconnaissance / target identification. The attacker obtains valid credentials for a Plane instance and is assigned membership in a workspace, potentially as a Guest with access to a single project. This is a low bar — a contractor, external collaborator, or lightly-vetted invited user suffices. The attacker identifies the target workspace
slug(visible to any authenticated member) and confirms that the instance exposes the REST API at/api/workspaces/{slug}/cycles/and/api/workspaces/{slug}/modules/.Triggering the flaw. Using an authenticated session, the attacker issues
GET /api/workspaces/{slug}/cycles/andGET /api/workspaces/{slug}/modules/. Because the endpoints lack theproject__project_projectmember__member=request.userfilter that their label and state siblings apply, the responses include records belonging to projects the attacker is not a member of — including private projects. No payload crafting or parameter manipulation is required beyond supplying the workspace slug; the authorization check is simply absent.Execution / collection. The responses are parsed for the exposed fields: cycle and module names, descriptions, sprint dates, issue counts, progress snapshots, external integration IDs, linked URLs, and member lists. The attacker can enumerate these values for every project in the workspace, then pivot using any linked URLs or external integration identifiers to locate related systems.
Post-exploitation impact. The attacker gains unauthorized visibility into private project planning data — an intelligence-gathering win useful for competitive reconnaissance, social engineering of project members whose identities are disclosed in member lists, and reconstructing an organization's roadmap. Because the access is read-only and the affected endpoints are not recursive into issue bodies, the direct blast radius is limited to planning metadata, consistent with the C/I/A profile above. There is no evidence of in-the-wild exploitation, CISA KEV listing, or public exploit availability at the time of writing.
Impact Assessment
The CVSS v3.1 base score is 4.3 (Medium), vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N. The network attack vector and low complexity make the issue trivially reachable by any authenticated user; the low privileges required means a Guest account is enough. There is no scope change — the flaw stays within Plane's authorization boundary. Integrity and availability impacts are None (read-only disclosure); confidentiality is Low, reflecting the exposure of project planning metadata and member lists rather than credentials or unrestricted private content.
Business impact centers on information disclosure: private sprint schedules, module scope, issue counts, progress snapshots, external integration IDs, and member rosters for projects a user was never authorized to see. This is meaningful for organizations that treat project plans, integration identifiers, and personnel mappings as sensitive. The blast radius is the entire workspace — every project's cycle and module records — for each authenticated workspace member, including guests. No EPSS score is published; no KEV or exploit evidence exists.
Detection Guidance
Sigma Rule
title: Plane Broken Object-Level Authorization - Unauthorized Cycle/Module Enumeration
id: 7b3f9c2e-1a4d-4e8b-9f21-cve2026104963
status: experimental
description: Detects authenticated requests to Plane workspace cycles/modules endpoints that may indicate access control probing across private projects
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-104963
author: valtersit.com
date: 2026/01/01
logsource:
category: webserver
detection:
selection_endpoint:
cs-uri-stem|contains:
- '/api/workspaces/'
cs-uri-stem|endswith:
- '/cycles/'
- '/modules/'
selection_method:
cs-method: 'GET'
condition: selection_endpoint and selection_method
fields:
- c-ip
- cs-username
- cs-uri-stem
- sc-status
falsepositives:
- Legitimate workspace administrators enumerating their own authorized projects
level: low
YARA Rule
rule CVE_2026_104963_Plane_Workspace_Enumeration
{
meta:
description = "Detects HTTP requests targeting Plane cycles/modules API endpoints implicated in CVE-2026-104963 broken access control"
author = "valtersit.com"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-104963"
date = "2026-01-01"
strings:
$endpoint_cycles = "/api/workspaces/" ascii wide nocase
$endpoint_modules = "/modules/" ascii wide nocase
$path_cycles = "/cycles/" ascii wide nocase
$method_get = "GET " ascii wide
condition:
uint16(0) == 0x4854 or uint16(0) == 0x4745 and
$endpoint_cycles and ($path_cycles or $endpoint_modules)
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-104963 Possible Plane Workspace Cycles/Modules Unauthorized Enumeration"; flow:to_server,established; http.method; content:"GET"; http.uri; content:"/api/workspaces/"; http.uri; content:"/cycles/"; http.uri; nocase; reference:cve,2026-104963; reference:url,nvd.nist.gov/vuln/detail/CVE-2026-104963; classtype:attempted-recon; sid:2026104963; rev:1;)
alert http any any -> any any (msg:"CVE-2026-104963 Possible Plane Workspace Modules Unauthorized Enumeration"; flow:to_server,established; http.method; content:"GET"; http.uri; content:"/api/workspaces/"; http.uri; content:"/modules/"; http.uri; nocase; reference:cve,2026-104963; reference:url,nvd.nist.gov/vuln/detail/CVE-2026-104963; classtype:attempted-recon; sid:2026104964; rev:1;)
Elastic Detection
sequence by user.name, source.ip with maxspan=5m
[ network where http.request.method == "GET" and
http.request.uri : "/api/workspaces/*" and
(http.request.uri : "*/cycles/*" or http.request.uri : "*/modules/*") and
http.response.status_code == 200 ]
Splunk SPL Query
index=web OR index=proxy
| search cs_method=GET
| search cs_uri_stem="/api/workspaces/*/cycles/*" OR cs_uri_stem="/api/workspaces/*/modules/*"
| stats count values(cs_uri_stem) as endpoints dc(cs_uri_stem) as unique_endpoints by src_ip user
| where unique_endpoints >= 2
| sort - unique_endpoints
Wazuh OSSEC Rule
<group name="plane,cve-2026-104963,">
<rule id="2026104" level="5">
<decoded_as>web-accesslog</decoded_as>
<field name="url">/api/workspaces/.*/(cycles|modules)/</field>
<description>CVE-2026-104963: Plane cycles/modules endpoint accessed - possible broken access control enumeration</description>
<mitre>
<id>T1213</id>
</mitre>
<options>no_full_log</options>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source).
Immediate mitigations. Because no vendor fix is confirmed in any tracked source despite the description referencing a 1.4.0 fix, treat this as unpatched operationally. Restrict workspace membership and Guest invitations to fully trusted principals. Where a reverse proxy or API gateway fronts Plane, add authorization logic that blocks or re-scopes
GET /api/workspaces/{slug}/cycles/andGET /api/workspaces/{slug}/modules/to the requester's own project memberships, mirroring the filter applied to the label and state endpoints. Audit existing Guest accounts and remove unnecessary ones. Monitor these two endpoints for anomalous enumeration patterns.Patch/upgrade steps. The NVD description states the issue is fixed in Plane 1.4.0. Confirm availability of that version through official Plane release channels and upgrade, then verify that the
project__project_projectmember__member=request.userfilter is present in bothWorkspaceCyclesEndpointandWorkspaceModulesEndpoint. Do not rely on unverified third-party mirrors.Long-term hardening. Apply consistent object-level authorization checks across all workspace endpoints by centralizing the membership filter rather than implementing it per-view. Add regression tests asserting that a Guest scoped to one project cannot retrieve cycles or modules from other projects. Treat sibling-endpoint divergence as a review trigger in code changes, and perform periodic access-control audits of workspace-scoped REST resources.
References
- NVD — CVE-2026-104963: https://nvd.nist.gov/vuln/detail/CVE-2026-104963
- Plane project and release notes (vendor): https://github.com/makeplane/plane/releases
- CWE-200 — Exposure of Sensitive Information to an Unauthorized Actor: https://cwe.mitre.org/data/definitions/200.html
- MITRE ATT&CK T1213 — Data from Information Repositories: https://attack.mitre.org/techniques/T1213/
- OWASP API Security Top 10 — API1: Broken Object Level Authorization: https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.