
Il sottosistema asset V2 di Plane si fidava degli slug degli spazi di lavoro e degli UUID degli asset senza applicare i giusti controlli di appartenenza, consentendo a un utente autenticato di leggere, copiare, eliminare e sovrascrivere asset in altri spazi di lavoro.
Il sottosistema asset V2 di Plane si fidava degli slug dei workspace e degli UUID degli asset senza imporre i necessari controlli di appartenenza, consentendo a un utente autenticato di leggere, copiare, eliminare e sovrascrivere asset in altri workspace.
Ho trovato questo problema mentre analizzavo Plane, la piattaforma open-source di project management, con una domanda molto specifica in mente:
Gli endpoint asset V2 impongono effettivamente i confini tra workspace, o si fidano troppo degli slug dei workspace e degli ID degli asset forniti dall'attaccante?
In questo caso, la risposta è stata no.
Il sottosistema asset V2 di Plane esponeva due falle di autorizzazione correlate che rompevano l'isolamento dei workspace per qualsiasi utente autenticato:
Ciò ha reso possibile l'abuso cross-workspace degli asset.
Nel mio PoC validato, un utente normale nel workspace Bravo è stato in grado di:
A quel problema è stato successivamente assegnato CVE-2026-46558.
Plane: Plane su GitHub
CVE: CVE-2026-46558
Questo ha interessato Plane, che sul suo sito ufficiale viene presentato come utilizzato da oltre 50.000 team in tutto il mondo. Plane evidenzia anche una forte adozione open-source, tra cui oltre 46.000 stelle su GitHub e oltre 1.000.000 di pull Docker, e mostra organizzazioni come Tencent, Accenture, Microsoft e Amazon.
attaccante autenticato nel workspace B → route asset V2 a livello di workspace si fida dello slug del workspace di destinazione e dell'UUID dell'asset senza controlli di appartenenza adeguati → lettura / patch / eliminazione presigned contro gli asset del workspace A + la ricerca dell'asset sorgente nella duplicazione si fida dell'UUID caricato → divulgazione, copia, eliminazione e sovrascrittura del branding cross-workspace
Plane è una piattaforma open-source di project management utilizzata per gestire:
Ciò significa che il suo sottosistema asset si trova su un vero confine di fiducia.
La domanda importante qui non era se Plane supporti i caricamenti.
La vera domanda era:
Plane impone l'isolamento dei workspace quando un utente autenticato fa riferimento ad asset di proprietà di un altro workspace?
In questo caso, non lo faceva.
Molte revisioni di applicazioni multi-tenant si concentrano prima sugli endpoint admin evidenti o sugli aggiornamenti diretti delle impostazioni.
Così facendo si perde una classe di bug molto comune e reale:
accesso a oggetti secondari attraverso sottosistemi di file o asset condivisi
I sistemi di asset sono facili da sbagliare perché spesso combinano:
Questo è esattamente il tipo di luogo in cui i confini tra tenant si indeboliscono silenziosamente.
Questo problema non riguardava la corruzione dello storage. Non riguardava S3 in sé. Non riguardava la gestione MIME dei caricamenti.
Era un fallimento del confine di autorizzazione:
Questo è sufficiente per creare una vulnerabilità reale.
Non ho affrontato Plane fuzzando ciecamente endpoint casuali o indovinando UUID senza alcun modello.
L'approccio più solido è stato identificare prima il confine di isolamento più promettente.
Per Plane, quello era il sottosistema asset V2.
Perché?
Perché un sistema di asset condiviso diventa pericoloso quando:
Quello era il confine giusto da ispezionare.
Ed era esattamente dove viveva il bug.
Si trattava in realtà di due fallimenti di autorizzazione correlati nello stesso sottosistema.
Le route degli asset a livello di workspace erano esposte attraverso:
apps/api/plane/app/urls/asset.py:50-56I gestori vulnerabili erano in:
apps/api/plane/app/views/asset/v2.py:314apps/api/plane/app/views/asset/v2.py:379apps/api/plane/app/views/asset/v2.py:400apps/api/plane/app/views/asset/v2.py:409Il problema era semplice.
WorkspaceFileAssetEndpoint accettava uno slug di workspace e un UUID di asset, quindi risolveva direttamente oggetti come:
workspace = Workspace.objects.get(slug=slug)
e:
asset = FileAsset.objects.get(id=asset_id, workspace__slug=slug)
senza prima imporre che il chiamante fosse effettivamente un membro autorizzato di quel workspace di destinazione.
Ciò significava che l'endpoint poteva comunque:
per oggetti di un altro workspace.
La route di duplicazione degli asset era mappata attraverso:
apps/api/plane/app/urls/asset.py:100-101La logica vulnerabile era in:
apps/api/plane/app/views/asset/v2.py:736-780Il workspace di destinazione aveva un decorator di autorizzazione. Ma la ricerca dell'asset sorgente no.
L'oggetto sorgente veniva caricato con:
original_asset = FileAsset.objects.filter(id=asset_id, is_uploaded=True).first()
Ciò significava che il chiamante necessitava solo:
Non c'era alcun controllo che il chiamante appartenesse al workspace sorgente che possedeva effettivamente quell'asset.
Questa è l'intera seconda falla.
La distinzione importante è l'impatto cross-workspace.
Molti bug di autorizzazione vengono minimizzati come:
"richiede comunque l'accesso"
Questo manca il punto.
La vera domanda non è:
"Il chiamante è autenticato?"
La vera domanda è:
"Il chiamante è autorizzato per lo specifico workspace e lo specifico asset su cui si sta operando?"
In Plane, la risposta era no.
Ciò trasforma quella che potrebbe sembrare una normale gestione di oggetti in un vero problema di sicurezza multi-tenant.
C'è una chiara differenza tra:
Questo problema era saldamente nel secondo caso.