Plane 1.3.1 - Stored XSS in intake issue description_html
Description
Plane CE 1.3.1 allows a low-privileged project member to submit arbitrary HTML/JS in the description_html field when creating an intake work item through the API v1 intake endpoint.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Affected products
1Patches
Vulnerability mechanics
Root cause
"Missing server-side HTML sanitization in the API v1 intake creation path allows arbitrary HTML/JavaScript to be persisted in the description_html field."
Attack vector
A low-privileged project member (including a guest with an API token) sends a POST request to `/api/v1/workspaces/{workspace_slug}/projects/{project_id}/intake-issues/` with attacker-controlled HTML/JavaScript in the `issue.description_html` field [ref_id=1]. The backend persists this payload without applying the existing nh3-based HTML sanitizer that normal issue serializers use. When a privileged user opens the intake work item view in the Plane UI, the stored JavaScript executes in that user's browser session, enabling data exfiltration or actions on behalf of the reviewing user [ref_id=1].
Affected code
The vulnerability resides in the API v1 intake creation endpoint (`plane/apps/api/plane/api/views/intake.py:190-193` and `plane/apps/api/plane/space/views/intake.py:145-148`). The intake view creates an Issue directly and assigns `description_html=issue_data.get("description_html", "<p></p>")`, bypassing `IssueSerializer.validate()` where `validate_html_content()` sanitizes HTML with nh3 (`plane/apps/api/plane/api/serializers/issue.py:93-94`). The malicious HTML is persisted in `Issue.description_html` and later rendered by the intake UI component (`plane/apps/web/core/components/inbox/content/issue-root.tsx:178`).
What the fix does
The advisory states that no patch is currently available [ref_id=1]. The root cause is that the intake creation path directly assigns `description_html` from the request data without passing it through `IssueSerializer.validate()`, which contains `validate_html_content()` that sanitizes HTML with the nh3 library. A proper fix would apply the same server-side HTML sanitization to the `description_html` field in the intake creation code path before persisting the Issue record.
Preconditions
- configIntake feature must be enabled for the project
- authAttacker must have a low-privileged project member account (including guest) with an API token
- inputAttacker sends POST request to the intake endpoint with crafted HTML/JS in description_html
- networkA privileged user must open the intake work item view to trigger the stored payload
Reproduction
Run Plane CE and create a workspace/project with Intake enabled. Create a low-privileged project user, generate an API token for that user, and submit an intake work item. The response is 201 Created. The returned issue detail contains the supplied description_html with the event handler still present. Log in as a workspace/project administrator. Open the project's Intake view and select the submitted work item. The stored payload executes in the administrator's browser context and displays an alert for document.domain.
Generated on Jun 18, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1- fluidattacks.com/es/advisories/earthmitrethird-party-advisory
News mentions
0No linked articles in our index yet.