CVE-2026-102988
Executive Summary
CVE-2026-102988 is an information disclosure vulnerability in Plane, an open-source project management tool. Prior to version 1.4.0, multiple issue-listing endpoints — including unauthenticated public deploy boards — pass a user-controlled order_by parameter to Django's ORM order_by without allowlist validation, enabling double-underscore relationship traversal across arbitrary related model fields. An unauthenticated remote attacker (CVSS 3.1: AV:N/AC:L/PR:N/UI:N) can exploit this weakness to leak database schema details via error messages and potentially disclose field values through differential ordering behavior, resulting in low-integrity confidentiality impact (C:L). The issue is rated 5.3 (Medium) and is fixed in Plane 1.4.0; no public PoC, exploit code, or Nuclei template is currently available, and CISA KEV listing is negative.
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 is a self-hostable, open-source project management and issue-tracking platform. The vulnerable component is the API layer under apps/api/plane/space/views/issue.py, which implements IssueListSpaceEndpoint. This endpoint serves public deploy boards (spaces) and is reachable without authentication. The endpoint accepts a client-supplied order_by parameter that is forwarded into the helper order_issue_queryset located at apps/api/plane/utils/order_queryset.py.
The core flaw is architectural: order_issue_queryset passes the user-controlled value directly into Django's QuerySet.order_by() without first validating it against an allowlist of permittable sort fields. Django's ORM supports double-underscore relationship traversal — a documented feature allowing cross-model joins such as relation__field. Because no allowlist constrains the input, an attacker may supply arbitrary traversal expressions targeting any field on any model reachable from the issue queryset through ForeignKey, ManyToMany, or OneToOne relationships.
This weakness is classified as CWE-943 — Improper Neutralization of Special Elements in Data Query Logic. There are two primary observable consequences:
- Schema disclosure via errors. Referencing a non-existent model field or an invalid relationship path causes Django to raise a field-lookup error. In debug or misconfigured deployments, the resulting response may expose internal model names, table names, or field names — revealing database schema details.
- Field-value disclosure via differential ordering (inference). Even without error leakage, valid traversal paths alter the ordering of returned issues. By observing how result ordering changes in response to crafted
order_byvalues, an attacker can perform a blind, boolean-style inference over related model fields — effectively enabling partial field-value reconstruction through differential response analysis.
The CVSS vector (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) confirms the attack is network-reachable, low complexity, requires no privileges or user interaction, scoped to a single security authority, and impacts confidentiality only — at low severity. Integrity and availability are unaffected, consistent with the read-only nature of an ORM ordering injection.
Critically, the same helper (order_issue_queryset) is consumed by what the advisory describes as multiple issue-listing endpoints, not just the public deploy board endpoint. This means authenticated and unauthenticated listing surfaces alike are potentially affected, expanding the reachable attack surface beyond the explicitly named IssueListSpaceEndpoint.
The root cause is a classic allowlist omission: ORM query modifiers derived from user input must be constrained to a fixed set of expected fields. Allowing unconstrained traversal enables metadata enumeration and — where the ORM permits it — cross-model inference leakage, without requiring direct injection of arbitrary SQL.
Exploitation Scenarios
No public proof-of-concept, exploit code, or Nuclei template exists for this CVE. The attack chain below is inferred strictly from the vulnerability class and the details in the NVD description; no specific payload strings or code patterns are fabricated.
Reconnaissance / target identification. The attacker identifies internet-facing Plane instances prior to 1.4.0 — self-hosted deployments, staging environments, and any instance exposing public "spaces" or deploy boards. Public deploy boards are the most attractive target because
IssueListSpaceEndpointhandles them without authentication (PR:N). Fingerprinting relies on Plane's standard HTTP responses and deployed asset paths.Triggering the flaw class. The attacker issues HTTP requests to an issue-listing endpoint, supplying a crafted value in the
order_byparameter. Becauseorder_issue_querysetapplies no allowlist, the supplied value reachesQuerySet.order_by()unmodified. The attacker first probes with invalid relationship-traversal expressions (double-underscore syntax) to elicit ORM field-lookup errors, then with valid traversals to observe ordering effects. No authentication or session is required against the public deploy board surface.Execution method (vulnerability-class level). The injection is exercised purely through the
order_byquery parameter string, using double-underscore relationship traversal to reference related model fields. Delivery is a standard HTTP GET/POST to the listing endpoint; there is no binary payload, no file write, and no shell interaction. Success is measured through two channels: (a) error responses that disclose schema identifiers, and (b) differential ordering of returned issue records.Post-exploitation impact. The attacker obtains schema metadata and, over repeated queries, may infer values of related model fields through differential ordering. This is a low-severity, read-only information disclosure — no code execution, no data modification, and no denial of service. However, leaked schema and field data may enable follow-on attacks: refined targeting of other vulnerabilities, social engineering using disclosed identifiers, or reconnaissance for subsequent privilege-escalation attempts. The impact is bounded by the CVSS C:L subscore and does not extend to integrity or availability.
Impact Assessment
The vulnerability affects Plane deployments running versions prior to 1.4.0, including self-hosted, cloud, and staging/dev instances that expose public deploy boards or any issue-listing endpoint that shares the vulnerable order_issue_queryset code path. Because the exploit requires only network access, low attack complexity, no privileges, and no user interaction, every unpatched, internet-exposed Plane instance is potentially in scope — a broad blast radius for a project-management tool frequently deployed as an internal-to-public service.
CVSS 3.1 subscores: AV:N (network exploitable), AC:L (no special conditions), PR:N (unauthenticated), UI:N (no interaction), S:U (impact scoped to the vulnerable component), C:L (low confidentiality impact), I:N (no integrity impact), A:N (no availability impact). Aggregate 5.3 (Medium).
Business impact centers on information disclosure rather than compromise:
- Data exposure: Database schema and potentially issue-field values may be enumerated, exposing internal data structures and metadata.
- Reconnaissance value: Leaked schema details can inform follow-on exploitation of other weaknesses in the same application.
- Compliance exposure: Disclosure of project metadata can implicate data-protection obligations if issue records contain sensitive business, customer, or personal data.
- No integrity/availability loss: The attacker cannot modify or delete records or degrade service via this flaw alone.
Given no evidence of active exploitation, no CISA KEV listing, and no EPSS score yet assigned by FIRST.org, the near-term likelihood is assessed as moderate-low, but the low exploitation barrier warrants prompt remediation.
Detection Guidance
Sigma Rule
title: Plane Issue-Listing order_by Relationship Traversal Attempt
id: 9f2c1a44-7b3e-4d21-9c88-2f6a1b0e5d77
status: experimental
description: Detects HTTP requests to Plane issue-listing endpoints containing double-underscore relationship traversal in the order_by parameter, indicative of CVE-2026-102988 exploitation.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-102988
author: valtersit.com
logsource:
category: webserver
detection:
selection_path:
cs-uri-stem|contains:
- '/issues/'
- '/issues'
selection_param:
cs-uri-query|contains: 'order_by='
selection_traversal:
cs-uri-query|contains: '__'
condition: selection_path and selection_param and selection_traversal
fields:
- c-ip
- cs-uri-stem
- cs-uri-query
- cs-user-agent
falsepositives:
- Legitimate administrative sorting on related fields
- Internal automated tooling using documented traversal sorting
level: medium
tags:
- attack.t1190
- cve.2026.102988
YARA Rule
rule CVE_2026_102988_Plane_Order_By_Traversal
{
meta:
author = "valtersit.com"
description = "Detects Plane order_by relationship-traversal exploitation attempts (CVE-2026-102988) in HTTP request logs or captures"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-102988"
date = "2026-01-01"
severity = "medium"
strings:
$p1 = "order_by=" ascii nocase
$p2 = "issues" ascii nocase
$t1 = "__" ascii
condition:
$p1 and $t1 and $p2 and #t1 >= 2
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-102988 Plane issue-list order_by relationship traversal attempt"; flow:to_server,established; http.uri; content:"order_by="; nocase; http.uri; content:"__"; fast_pattern; http.uri; pcre:"/order_by=[^&]*__[^&]*/i"; classtype:attempted-recon; sid:2026102988; rev:1; reference:cve,2026-102988; metadata:created_at 2026_01_01, updated_at 2026_01_01;)
Elastic Detection
sequence by source.ip with maxspan=30s
[http where http.request.method in ("GET","POST") and
wildcard(url.query, "*order_by=*") and
wildcard(url.query, "*__*") and
wildcard(url.path, "*issues*")]
Splunk SPL Query
index=web sourcetype=access_combined
| eval raw = uri_query
| where match(raw, "order_by=") AND match(raw, "__")
| where match(uri_path, "issues")
| stats count min(_time) as first_seen max(_time) as last_seen
values(uri_query) as queries by src_ip
| where count >= 3
| eval first_seen = strftime(first_seen, "%Y-%m-%d %H:%M:%S")
| eval last_seen = strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Wazuh OSSEC Rule
<group name="web,plane,">
<rule id="2026102" level="10">
<if_sid>31100</if_sid>
<url>order_by=</url>
<match>__</match>
<match>issues</match>
<description>CVE-2026-102988: Plane issue-listing order_by relationship-traversal exploitation attempt detected</description>
<mitre>
<id>T1190</id>
</mitre>
<group>cve_2026_102988,recon,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source). The advisory text states the issue is fixed in version 1.4.0, but no vendor advisory URL, commit hash, or confirmed release artifact has surfaced through tracked patch sources. Treat any mitigation below as compensatory until a verifiable 1.4.0+ artifact is independently confirmed.
1) Immediate mitigations (no code change required):
- Restrict or disable public deploy boards / spaces to prevent unauthenticated access to
IssueListSpaceEndpoint. Require authentication at the reverse proxy or WAF layer for all issue-listing routes. - Deploy a WAF rule (or equivalent reverse-proxy filter) that rejects requests where the
order_byparameter contains double-underscore (__) traversal sequences, until the application is patched. - Run Plane with Django
DEBUG = Falsein every environment to suppress verbatim ORM error messages that leak schema details. - Reduce information surface: restrict network exposure of Plane instances to trusted networks or VPN-only access.
- Monitor web logs for
order_byvalues containing__as an exploitation indicator (see Detection Guidance).
2) Patch / upgrade steps:
- Upgrade to Plane 1.4.0 or later as soon as a verified vendor release is available. Confirm the affected code path in
apps/api/plane/utils/order_queryset.pynow enforces an allowlist. - After upgrade, re-verify that public deploy board routes no longer accept unvalidated
order_bytraversal input. - Validate the upgrade against a staging clone of production before rollout; back up the database first.
3) Long-term hardening:
- Enforce parameter allowlisting on all ORM-facing query parameters (
order_by, filters, sorting), rejecting any input not matching a fixed set of expected field names. - Adopt secure-code review and unit tests that assert rejection of double-underscore traversal input on listing endpoints.
- Apply defense in depth: WAF filtering, authentication for list endpoints, deterministic error handling, and least-privilege database accounts.
- Maintain a documented dependency and vulnerability-management cadence for self-hosted open-source tools such as Plane.
References
- NVD — CVE-2026-102988: https://nvd.nist.gov/vuln/detail/CVE-2026-102988
- Plane project (open-source project management tool): https://github.com/makeplane/plane
- CWE-943 — Improper Neutralization of Special Elements in Data Query Logic: https://cwe.mitre.org/data/definitions/943.html
- Django documentation — QuerySet.order_by and field lookups (double-underscore traversal): https://docs.djangoproject.com/en/stable/ref/models/querysets/#order-by
- FIRST.org EPSS (score not yet assigned for this CVE): https://www.first.org/epss/
No exploit-in-the-wild evidence, threat actor campaign, or CISA KEV listing is associated with CVE-2026-102988 at this time.
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.