Skip to main content
Vulnerability Database/CVE-2026-105636

CVE-2026-105636: Plane Project Management Tool SSRF Vulnerability

CVE-2026-105636 is a server-side request forgery flaw in Plane project management tool that allows attackers to access internal resources through redirect chains. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-105636 Overview

CVE-2026-105636 is a Server-Side Request Forgery (SSRF) [CWE-918] vulnerability in Plane, an open-source project management tool. The flaw affects the webhook delivery task in apps/api/plane/bgtasks/webhook_task.py in versions prior to 1.4.0. While Plane's validate_url() blocks private, loopback, link-local, and reserved addresses for the registered webhook URL, the delivery task calls requests.post() without allow_redirects=False and never re-validates the final destination after HTTP redirects. Authenticated users who can create a workspace can abuse this to pivot requests to internal services, including cloud instance metadata, and read responses through the workspace webhook-logs API.

Critical Impact

Any workspace creator can exfiltrate internal network data and cloud metadata credentials by registering a webhook that redirects to internal endpoints, with responses retrievable via the webhook-logs API.

Affected Products

  • Plane (makeplane/plane) versions prior to 1.4.0
  • Plane self-hosted deployments exposing workspace webhook functionality
  • Plane instances running on cloud providers with Instance Metadata Service (IMDS) endpoints reachable from the worker

Discovery Timeline

  • 2026-10-05 - CVE-2026-105636 published to NVD
  • 2026-10-07 - Last updated in NVD database

Technical Details for CVE-2026-105636

Vulnerability Analysis

The flaw is a classic SSRF caused by trusting a one-time URL validation while allowing unrestricted HTTP redirects. Plane's webhook subsystem validates the user-supplied webhook URL through validate_url(), which rejects private, loopback, link-local, and reserved IP ranges. However, the background delivery task invokes requests.post() with default redirect behavior, so a 302 response from an attacker-controlled host causes the Python requests library to transparently follow the redirect to any internal address.

The worker then stores the response body in webhook_logs. The workspace webhook-logs API exposes those logs to the attacker, turning the SSRF into a readable, two-way data channel. On cloud deployments, this includes IMDS endpoints such as AWS http://169.254.169.254/latest/meta-data/, enabling retrieval of IAM role credentials.

Root Cause

The root cause is incomplete URL validation across the request lifecycle. validate_url() is only applied to the originally registered webhook target. The HTTP client follows redirects by default and does not re-run validate_url() against intermediate or final URLs. There is also no network-layer egress filtering preventing the worker process from reaching link-local or RFC1918 addresses.

Attack Vector

An attacker with permission to create a workspace registers a webhook pointing to a public server they control. When Plane triggers the webhook, the attacker's server returns an HTTP 302 to an internal URL such as http://169.254.169.254/latest/meta-data/iam/security-credentials/. The Plane worker follows the redirect, fetches the internal response, and persists it in webhook_logs. The attacker reads the captured body through the webhook-logs API.

python
# Patch excerpt from apps/api/plane/authentication/adapter/base.py
# Replaces direct `requests` usage with a hardened fetch helper
# that re-validates URLs across redirects.
 import uuid
 from io import BytesIO

-import requests
 from django.conf import settings
 from django.core.exceptions import ValidationError
 from django.core.validators import validate_email
+from plane.utils.url_security import pinned_fetch_following_redirects

 # Django imports
 from django.utils import timezone
# Source: https://github.com/makeplane/plane/commit/04622ce1188c4680951f0001e35efb342fe51615

Detection Methods for CVE-2026-105636

Indicators of Compromise

  • Webhook registrations whose public target responds with 3xx redirects to RFC1918, loopback, or link-local addresses such as 169.254.169.254.
  • Entries in webhook_logs containing response bodies that resemble cloud metadata, IAM credentials, or internal service banners.
  • Outbound requests from Plane worker hosts to 169.254.169.254, metadata.google.internal, or 169.254.170.2.
  • Repeated webhook creation and deletion by a single workspace user correlated with unusual webhook-log reads.

Detection Strategies

  • Inspect Plane application logs for webhook delivery responses that follow redirects, and alert when the final response host differs from the registered host.
  • Monitor the webhook-logs API for high-volume reads shortly after webhook creation events.
  • Correlate egress network flows from Plane worker containers against an allowlist that excludes link-local and private ranges.

Monitoring Recommendations

  • Enable DNS query logging on the Plane worker to detect lookups of internal hostnames triggered by webhook deliveries.
  • Capture and retain cloud VPC flow logs for Plane worker subnets to identify SSRF attempts against IMDS.
  • Alert on IMDSv1 token-less requests originating from the Plane worker and migrate to IMDSv2 where supported.

How to Mitigate CVE-2026-105636

Immediate Actions Required

  • Upgrade Plane to version 1.4.0 or later, which introduces pinned_fetch_following_redirects to re-validate URLs across redirects.
  • Rotate any cloud IAM credentials, API tokens, or secrets reachable from the Plane worker's network position.
  • Audit existing webhook_logs for responses containing metadata, credentials, or other internal service data.

Patch Information

The fix is included in Plane release v1.4.0 and tracked in GitHub Pull Request #9163 and commit 04622ce. Full details are available in the GitHub Security Advisory GHSA-mq87-52pf-hm3h and GitHub Release v1.4.0.

Workarounds

  • Enforce IMDSv2 on AWS instances hosting Plane workers to require session tokens for metadata access.
  • Apply network egress policies that block Plane worker pods from reaching 169.254.0.0/16, RFC1918 ranges, and loopback addresses.
  • Restrict workspace creation to trusted users until the upgrade is applied.
bash
# Example Kubernetes NetworkPolicy snippet blocking IMDS egress for Plane workers
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: plane-worker-block-metadata
spec:
  podSelector:
    matchLabels:
      app: plane-worker
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 169.254.0.0/16
              - 10.0.0.0/8
              - 172.16.0.0/12
              - 192.168.0.0/16
              - 127.0.0.0/8

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.