← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2025-21616 · CWE-79 · Disclosed 2025-01-06

Plane is an open-source project management tool

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a poisoned employee badge, not a skeleton key to the building

CVE-2025-21616 is a stored XSS bug in Plane's profile-image upload path. In Plane versions earlier than 0.23, an authenticated user can upload an SVG avatar containing JavaScript; that script runs in another user's browser when the victim views the profile or any page that renders that avatar. The affected component is the Plane API service's profile image upload feature, and the vulnerable range is < 0.23 on all deployment platforms.

The vendor's 5.4 MEDIUM rating is defensible in a lab, but a bit generous for enterprise patch triage. The decisive friction is that exploitation already assumes a valid Plane account and then still needs a victim to render the malicious avatar, which makes this a *post-initial-access, user-interaction-dependent* browser-session issue rather than an initial foothold or infrastructure-level compromise path.

"Stored XSS is real here, but it needs a logged-in attacker and a victim view, so this is backlog work, not a fire drill."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Get a Plane account

The attacker needs working access to the target Plane workspace, whether through self-signup, guest invitation, stolen credentials, or an already-compromised user. Tools are ordinary browser workflow or credential abuse tooling such as Burp Suite for session handling and request replay. This is the biggest real-world gate because the bug is not usable by an unauthenticated internet rando.
Conditions required:
  • Attacker has valid Plane credentials or equivalent session access
  • Target organization actually runs self-hosted Plane
  • Attacker can reach the same tenant/workspace as intended victims
Where this breaks in practice:
  • Many Plane deployments are internal-only or behind SSO
  • Guest/member onboarding may be restricted to admins
  • Compromising a valid user is already a separate security event
Detection/coverage: External perimeter scanners usually miss this prerequisite entirely. IAM, IdP, and Plane audit logs are more useful than vulnerability scanners here.
STEP 02

Upload a weaponized SVG avatar

Using a browser or Burp Suite, the attacker uploads an SVG file with embedded JavaScript as a profile image. The GHSA advisory includes a minimal PoC SVG with inline script, so exploit construction is trivial once authenticated. Because the payload is stored server-side, this is a persistent rather than reflected client-side issue.
Conditions required:
  • Profile image upload accepts SVG content
  • Server-side validation or sanitization is absent
  • Uploaded asset is later rendered by other users' browsers
Where this breaks in practice:
  • Some reverse proxies, storage tiers, or custom WAF rules may already block image/svg+xml
  • Tenant-specific hardening may strip or deny active SVG content
  • If avatars are disabled or tightly controlled, the path disappears
Detection/coverage: SAST/CodeQL may spot unsafe file handling patterns, but reliable confirmation usually needs authenticated DAST or manual testing. Commodity infra scanners have weak coverage.
STEP 03

Wait for a victim to render the avatar

The malicious code only fires when another user loads a page that displays the attacker's avatar, such as a profile page or activity surface. The practical weapon here is social placement, not packet spraying: the attacker relies on normal collaboration patterns to get eyeballs on the avatar. Burp Collaborator-style callbacks or browser devtools can confirm render-time execution.
Conditions required:
  • A victim user visits a page that renders the avatar
  • The victim browser executes the SVG's script content
  • The victim session is sufficiently privileged to matter
Where this breaks in practice:
  • User interaction is mandatory
  • Low-value or inactive accounts may never be viewed
  • Modern CSP or browser behavior can break some payload styles
Detection/coverage: This is where client-side telemetry matters. Web proxy logs, CSP violation reports, and browser security tooling are more helpful than host EDR on the Plane server.
STEP 04

Abuse the victim session in-browser

Once executed, the JavaScript can perform same-origin actions as the victim, scrape visible data, or attempt session/token theft depending on cookie and frontend handling. Typical tooling is plain browser fetch() abuse or scripted DOM interaction; no memory corruption or server RCE chain is involved. Impact stays bounded to what the victim can do in Plane and what the browser session exposes.
Conditions required:
  • Victim has meaningful Plane privileges
  • Session artifacts or sensitive UI/API actions are reachable from browser context
  • No CSP or frontend protections block the exfiltration/action path
Where this breaks in practice:
  • Impact is tenant-local and browser-session-local, not host-level compromise
  • HttpOnly cookies and stronger CSP reduce easy token theft paths
  • Server-side authorization still limits what the victim account can do
Detection/coverage: App-layer anomaly detection may catch unusual actions from a legitimate session, but most VA scanners stop before proving impact. Expect mixed detection quality.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo primary-source evidence of active exploitation found, and not listed in CISA KEV as checked against the official catalog.
Proof of conceptPublic PoC exists inside the vendor GitHub advisory as a minimal malicious SVG payload. I did not find a separate weaponized exploit framework in primary sources.
EPSS0.01012 from your intel block, which is low. EPSS percentile was not independently verified from a primary source during this review.
KEV statusNo. The authoritative KEV reference is the CISA Known Exploited Vulnerabilities Catalog.
CVSS vector meaningAV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N translates to remote reachability, but only after authentication and victim interaction, with low C/I impact and no direct availability hit.
Affected versionsPlane < 0.23; affected service is the Plane API Service profile image upload feature, on all supported deployment platforms.
Fixed versionVendor fix is 0.23 or later. Ubuntu's tracker says the issue does not apply to software found in Ubuntu, so there is no distro backport story to lean on there.
Exposure / population realityPlane is not obscure: the vendor advertises 1,000,000+ Docker pulls and thousands of production environments, so the software exists in the wild. That said, the *reachable vulnerable population* is narrower because this bug still needs a logged-in attacker inside the same workspace.
DisclosurePublished 2025-01-06 via GitHub advisory GHSA-rcg8-g69v-x23j; NVD shows the CVE was received from GitHub on the same date.
Researcher / sourceGitHub advisory published by sriramveeraghanta on behalf of the project's security advisory flow.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.6/10)

The single biggest downward pressure is attacker position: this bug requires an authenticated user in the target Plane workspace before anything interesting can happen. That makes it a *foothold amplifier* inside a collaboration app, not an initial-access or infrastructure-compromise event.

HIGH Affected version range and fixed version
HIGH Authenticated + victim-view prerequisites
MEDIUM Real-world exposure population and exploit prevalence

Why this verdict

  • Start from 5.4 MEDIUM, then cut for attacker position: exploitation requires a valid Plane account (PR:L), which means the attacker is already inside the tenant or has already stolen creds.
  • Cut again for mandatory user interaction: this is stored XSS, but the payload still needs another user to load a page rendering the avatar (UI:R), so exploitation is not self-driving at internet scale.
  • Cut for bounded blast radius, add back a little for persistence: impact is generally limited to the victim's Plane browser session and privileges, but the payload is stored and can hit multiple viewers over time in collaborative workflows.

Why not higher?

There is no unauthenticated reach, no direct server-side code execution, and no infrastructure takeover path in the advisory. Requiring *both* a logged-in attacker and a victim page view is compounded friction that keeps this out of MEDIUM/HIGH operational urgency for most enterprises.

Why not lower?

This is still a real stored XSS in a shared work-management platform, not a theoretical parser bug. In environments with external guests, contractors, or broadly shared workspaces, a single low-privilege user could target admins or project owners and perform actions in their browser context.

05 · Compensating Control

What to do — in priority order.

  1. Block SVG avatar uploads — Deny image/svg+xml for profile images at the application, reverse proxy, or object-storage ingress layer. For a LOW verdict there is no SLA (treat as backlog hygiene), so do this in the next normal config cycle if you cannot upgrade immediately.
  2. Enforce a tight CSP — Add or verify a Content Security Policy that prevents inline script execution and sharply restricts script sources for user-rendered content. This is an effective brake on browser-side payload execution and is the vendor's own fallback recommendation; for LOW, deploy during routine hardening rather than as emergency change.
  3. Constrain who can join the workspace — Limit guest invitations, self-signup, and dormant low-trust accounts because the exploit begins with a valid Plane identity. For LOW, there is no mitigation SLA, but this is smart hygiene for any externally shared collaboration stack.
  4. Review internet exposure and privileged users — If your Plane instance is exposed beyond VPN or has external collaborators, prioritize checking whether admins and automation users frequently view user profiles or activity feeds. This does not change the formal SLA bucket, but it tells you whether your local risk sits at the top or bottom of that LOW band.
What doesn't work
  • MFA alone does not fix this; MFA helps stop account theft, but a legitimate or already-compromised Plane user can still upload the malicious SVG.
  • Server-side EDR is weak coverage because the exploit executes in the victim browser, not as a process on the Plane host.
  • Unauthenticated perimeter scans will often miss this entirely because the vulnerable path is behind login and needs a multi-step stored-XSS workflow.
06 · Verification

Crowdsourced verification payload.

Run this on the Plane host or from an auditor shell with read access to the deployment files; it can inspect a supplied Docker Compose file and, if available, running Docker containers. Invoke it as bash check_plane_cve_2025_21616.sh /opt/plane/docker-compose.yml; root is not required unless your Docker socket is root-only.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_plane_cve_2025_21616.sh
# Detect likely exposure to CVE-2025-21616 in self-hosted Plane deployments.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -u

THRESHOLD="0.23.0"
COMPOSE_FILE="${1:-}"
FOUND_ANY=0
FOUND_VULN=0
FOUND_UNKNOWN=0

declare -a TAGS

normalize_tag() {
  local t="$1"
  t="${t#v}"
  t="${t%%-*}"
  echo "$t"
}

is_semver_like() {
  [[ "$1" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]
}

version_lt() {
  local a="$1"
  local b="$2"
  [[ "$(printf '%s\n%s\n' "$a" "$b" | sort -V | head -n1)" != "$b" && "$a" != "$b" ]]
}

collect_from_compose() {
  local file="$1"
  [[ -f "$file" ]] || return 0
  while IFS= read -r line; do
    line="$(echo "$line" | sed -E 's/#.*$//')"
    if echo "$line" | grep -Eq 'image:[[:space:]]*.*makeplane/'; then
      img="$(echo "$line" | sed -E 's/.*image:[[:space:]]*//')"
      tag="${img##*:}"
      if [[ "$img" == "$tag" ]]; then
        TAGS+=("UNKNOWN")
      else
        TAGS+=("$tag")
      fi
    fi
  done < "$file"
}

collect_from_docker() {
  if ! command -v docker >/dev/null 2>&1; then
    return 0
  fi

  local images
  images="$(docker ps --format '{{.Image}}' 2>/dev/null | grep 'makeplane/' || true)"
  [[ -n "$images" ]] || return 0

  while IFS= read -r img; do
    [[ -n "$img" ]] || continue
    tag="${img##*:}"
    if [[ "$img" == "$tag" ]]; then
      TAGS+=("UNKNOWN")
    else
      TAGS+=("$tag")
    fi
  done <<< "$images"
}

evaluate_tags() {
  local seen=0
  for raw in "${TAGS[@]}"; do
    seen=1
    FOUND_ANY=1
    if [[ "$raw" == "latest" || "$raw" == "stable" || "$raw" == "dev" || "$raw" == "buildcache" || "$raw" == "UNKNOWN" || -z "$raw" ]]; then
      FOUND_UNKNOWN=1
      continue
    fi

    ver="$(normalize_tag "$raw")"
    if ! is_semver_like "$ver"; then
      FOUND_UNKNOWN=1
      continue
    fi

    # Fixed in 0.23 and later; any 1.x/2.x release is therefore patched.
    if version_lt "$ver" "$THRESHOLD"; then
      FOUND_VULN=1
    fi
  done

  [[ $seen -eq 1 ]] || FOUND_UNKNOWN=1
}

collect_from_compose "$COMPOSE_FILE"
collect_from_docker

evaluate_tags

if [[ $FOUND_VULN -eq 1 ]]; then
  echo "VULNERABLE"
  exit 1
fi

if [[ $FOUND_ANY -eq 1 && $FOUND_UNKNOWN -eq 0 ]]; then
  echo "PATCHED"
  exit 0
fi

echo "UNKNOWN"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, first confirm whether you actually run self-hosted Plane and whether any instance is still below 0.23; if yes, this is not an emergency patch unless your Plane tenant is open to contractors, guests, or broad external collaboration. Under the noisgate mitigation SLA for a LOW finding there is no SLA (treat as backlog hygiene), and under the noisgate remediation SLA there is likewise no fixed deadline—so block SVG avatar uploads if that is easy, then roll 0.23+ into the next routine Plane maintenance cycle and document any deferral rationale.

Sources

  1. GitHub advisory GHSA-rcg8-g69v-x23j
  2. NVD CVE-2025-21616
  3. OSV record for CVE-2025-21616
  4. Plane self-hosting editions documentation
  5. Plane open-source product page
  6. Plane security page
  7. Ubuntu tracker for CVE-2025-21616
  8. CISA Known Exploited Vulnerabilities Catalog
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.