Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-46558 — Plane’s V2 asset subsystem trusted workspace slugs and asset UUIDs without enforcing the right membership checks, which let one authenticated user read, copy, delete, and overwrite assets in other workspaces. | Kitploit
Tools/GitHubGitHub/0xmrma/cve-2026-46558
Vulnerability AnalysisWeb Application ExploitationPenetration TestingPapers & ResearchLearning & EducationCurated Resources
GitHub0xmrma/cve-2026-46558

CVE-2026-46558

Plane’s V2 asset subsystem trusted workspace slugs and asset UUIDs without enforcing the right membership checks, which let one authenticated user read, copy, delete, and overwrite assets in other workspaces.

View Repository
73 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-46558

Plane’s V2 asset subsystem trusted workspace slugs and asset UUIDs without enforcing the right membership checks, which let one authenticated user read, copy, delete, and overwrite assets in other workspaces.

Intro

I found this issue while reviewing Plane, the open-source project management platform, with a very specific question in mind:

Do the V2 asset endpoints actually enforce workspace boundaries, or do they trust attacker-supplied workspace slugs and asset IDs too far?

In this case, the answer was no.

Plane’s V2 asset subsystem exposed two related authorization flaws that broke workspace isolation for any authenticated user:

  • the workspace-level asset endpoint did not enforce target-workspace membership before asset operations
  • the duplicate-assets flow authorized only the destination workspace and trusted the source asset UUID without checking source-workspace access

That made cross-workspace asset abuse possible.

In my validated PoC, one normal user in workspace Bravo was able to:

  • download Alpha’s private uploaded asset
  • duplicate that asset into Bravo’s own workspace
  • delete Alpha’s original asset
  • overwrite Alpha’s workspace logo with attacker-controlled content

That issue was later assigned CVE-2026-46558.

Plane: Plane on GitHub
CVE: CVE-2026-46558

This affected Plane, which on its official site is presented as being used by 50,000+ teams across the globe. Plane also highlights strong open-source adoption, including 46,000+ GitHub stars and 1,000,000+ Docker pulls, and showcases organizations such as Tencent, Accenture, Microsoft, and Amazon.

photo0

Attack Chain

authenticated attacker in workspace B → workspace-level V2 asset route trusts target workspace slug and asset UUID without proper membership checks → presigned read / patch / delete against workspace A assets + duplicate-assets source lookup trusts uploaded source UUID → cross-workspace disclosure, copying, deletion, and branding overwrite


What Plane Does

Plane is an open-source project management platform used to manage:

  • tasks
  • issues
  • sprints
  • docs
  • triage
  • workspace-level branding and assets

That means its asset subsystem sits on a real trust boundary.

The important question here was not whether Plane supports uploads.

The real question was:

Does Plane enforce workspace isolation when one authenticated user references assets owned by another workspace?

In this case, it did not.


Why This Bug Was Worth Looking At

A lot of multi-tenant application reviews focus first on obvious admin endpoints or direct settings updates.

That misses a very common and very real bug class:

secondary object access through shared file or asset subsystems

Asset systems are easy to get wrong because they often combine:

  • user-controlled identifiers
  • storage-layer indirection
  • metadata-driven object linking
  • presigned URL generation
  • multiple entity types behind a shared route

That is exactly the kind of place where tenant boundaries silently weaken.

This issue was not about storage corruption. It was not about S3 itself. It was not about upload MIME handling.

It was an authorization boundary failure:

  • attacker-controlled identifiers crossed the boundary
  • the server resolved cross-workspace objects
  • authorization was incomplete or missing
  • privileged asset actions still succeeded

That is enough to create a real vulnerability.


The Boundary I Focused On

I did not approach Plane by blindly fuzzing random endpoints or guessing at UUIDs with no model.

The stronger approach was to identify the most promising isolation boundary first.

For Plane, that was the V2 asset subsystem.

Why?

Because a shared asset system becomes dangerous when:

  • multiple workspaces exist
  • uploaded objects are referenced by UUID
  • workspace slugs are attacker-controlled route inputs
  • the application later turns successful lookups into presigned download or mutation paths

That was the right boundary to inspect.

And it was exactly where the bug lived.


Root Cause

This was really two related authorization failures in the same subsystem.

Root cause 1: workspace asset routes missing membership enforcement

The workspace-level asset routes were exposed through:

  • apps/api/plane/app/urls/asset.py:50-56

The vulnerable handlers were in:

  • apps/api/plane/app/views/asset/v2.py:314
  • apps/api/plane/app/views/asset/v2.py:379
  • apps/api/plane/app/views/asset/v2.py:400
  • apps/api/plane/app/views/asset/v2.py:409

The problem was simple.

WorkspaceFileAssetEndpoint accepted a workspace slug and asset UUID, then directly resolved objects like:

workspace = Workspace.objects.get(slug=slug)

and:

asset = FileAsset.objects.get(id=asset_id, workspace__slug=slug)

without first enforcing that the caller was actually an authorized member of that target workspace.

That meant the endpoint could still:

  • create assets
  • finalize assets
  • delete assets
  • return presigned download URLs

for another workspace’s objects.

Root cause 2: duplicate-assets trusted the source asset UUID

The duplicate-assets route was mapped through:

  • apps/api/plane/app/urls/asset.py:100-101

The vulnerable logic was in:

  • apps/api/plane/app/views/asset/v2.py:736-780

The destination workspace had an authorization decorator. But the source asset lookup did not.

The source object was loaded with:

original_asset = FileAsset.objects.filter(id=asset_id, is_uploaded=True).first()

That meant the caller only needed:

  • valid access to the destination workspace
  • a source asset UUID that was uploaded

There was no check that the caller belonged to the source workspace that actually owned that asset.

That is the whole second bug.


Why This Is a Security Issue, Not Just Bad Access Logic

The important distinction is cross-workspace impact.

A lot of authorization bugs get minimized as:

“it still requires login”

That misses the point.

The real question is not:

“Is the caller authenticated?”

The real question is:

“Is the caller authorized for the specific workspace and specific asset being acted on?”

In Plane, that answer was no.

That turns what might look like ordinary object handling into a real multi-tenant security issue.

There is a clear difference between:

  • authenticated access inside your own workspace
  • and authenticated access that crosses another tenant’s boundary

This issue was firmly the second case.


PoC

I validated the issue locally against Plane Community Edition 1.2.3 using two ordinary users in two unrelated workspaces:

  • Alpha in workspace alpha-20260323072017
  • Bravo in workspace bravo-20260323072017

I used Alpha to create a legitimate private uploaded asset in a project issue.

The validated private asset ID in my run was:

6ed6ed62-d1b2-4399-8220-336c01b7d72c

Case 1: unauthorized read from another workspace

As Bravo, I requested:

GET /api/assets/v2/workspaces/alpha-20260323072017/6ed6ed62-d1b2-4399-8220-336c01b7d72c/

Plane returned:

HTTP/1.1 302 Found

with a presigned download URL for Alpha’s asset.

The downloaded file hash matched Alpha’s original private asset exactly:

original:          0d4d070f550ba59ba6b30bee62343cf68ea221af7034f131f72f6409cf5a598e
unauthorized read: 0d4d070f550ba59ba6b30bee62343cf68ea221af7034f131f72f6409cf5a598e

That proved the read path crossed workspace boundaries successfully.


Case 2: cross-workspace duplication through source UUID trust

As Bravo, I then requested:

Download Tool