
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 e , e mostra organizzazioni come , , e .

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.
Ho validato il problema localmente contro Plane Community Edition 1.2.3 usando due utenti ordinari in due workspace non correlati:
alpha-20260323072017bravo-20260323072017Ho usato Alpha per creare un asset privato legittimo caricato in un issue di progetto.
L'ID dell'asset privato validato nella mia esecuzione era:
6ed6ed62-d1b2-4399-8220-336c01b7d72c
Come Bravo, ho richiesto:
GET /api/assets/v2/workspaces/alpha-20260323072017/6ed6ed62-d1b2-4399-8220-336c01b7d72c/
Plane ha restituito:
HTTP/1.1 302 Found
con un URL di download presigned per l'asset di Alpha.
L'hash del file scaricato corrispondeva esattamente all'asset privato originale di Alpha:
originale: 0d4d070f550ba59ba6b30bee62343cf68ea221af7034f131f72f6409cf5a598e
lettura non autorizzata: 0d4d070f550ba59ba6b30bee62343cf68ea221af7034f131f72f6409cf5a598e
Ciò ha dimostrato che il percorso di lettura attraversava con successo i confini dei workspace.
Come Bravo, ho quindi richiesto:
POST /api/assets/v2/workspaces/bravo-20260323072017/duplicate-assets/6ed6ed62-d1b2-4399-8220-336c01b7d72c/
Plane ha restituito:
HTTP/1.1 200 OK
e ha creato un asset duplicato dalla parte dell'attaccante:
72d51497-ccc1-4546-ba14-28fae5d37dbb
Lo SHA-256 del file duplicato corrispondeva esattamente all'asset originale di Alpha:
0d4d070f550ba59ba6b30bee62343cf68ea221af7034f131f72f6409cf5a598e
Ciò ha dimostrato che il solo UUID dell'asset sorgente era sufficiente per copiare contenuti cross-workspace in un workspace controllato dall'attaccante.
Come Bravo, ho quindi inviato:
DELETE /api/assets/v2/workspaces/alpha-20260323072017/6ed6ed62-d1b2-4399-8220-336c01b7d72c/
Plane ha restituito:
HTTP/1.1 204 No Content
Quando Alpha ha successivamente recuperato quell'asset, il server ha restituito:
HTTP/1.1 404 Not Found
Ciò ha dimostrato un impatto sull'integrità cross-workspace, non solo una divulgazione.
Come Bravo, ho creato un asset WORKSPACE_LOGO contro il workspace di Alpha attraverso la vulnerabile route degli asset a livello di workspace, ho caricato contenuti controllati dall'attaccante e l'ho finalizzato.
Dopodiché, i metadati del workspace di Alpha puntavano all'asset logo controllato dall'attaccante:
c1032f06-3cf5-4f7e-b139-e6976d8c567d
L'hash del logo finale scaricato corrispondeva esattamente al payload dell'attaccante:
atteso: b9d1ef1de88d61bf55dd18055839bacacb832a752e17a7312547f641113d0e7b
osservato: b9d1ef1de88d61bf55dd18055839bacacb832a752e17a7312547f641113d0e7b
Ciò ha dimostrato un percorso visibile di sovrascrittura cross-workspace, non solo un problema di accesso al backend nascosto.
Ciascuno dei risultati sopra sarebbe già stato sufficiente per giustificare un vero report di bug.
Ma validare l'intera catena era importante per due ragioni.
Mostrava che il problema non era limitato a un'esposizione di sola lettura.
Lo stesso confine debole abilitava:
Ciò rende l'impatto molto più forte di un IDOR ristretto del tipo "può recuperare un file".
Mostrava che i due percorsi di codice erano correlati ma indipendentemente importanti.
Una falla esponeva direttamente le operazioni sugli asset a livello di workspace. La seconda falla trasformava gli UUID degli asset caricati in una primitiva di esfiltrazione riutilizzabile tramite duplicazione.
Ciò rendeva la storia di sicurezza complessiva molto più difficile da liquidare.
L'impatto di sovrascrittura più visibile che ho validato è stato:
WORKSPACE_LOGOÈ stato deliberato perché è facile da verificare e dimostra un evidente fallimento di integrità cross-tenant.
Ma l'endpoint non era limitato ai loghi dei workspace.
Il flusso vulnerabile degli asset a livello di workspace accettava anche diversi contesti di entità, tra cui:
Ciò era importante perché mostrava che il bug era strutturale, non legato a un singolo campo di branding.
Ho validato direttamente il percorso del logo del workspace. Il percorso di codice più ampio suggeriva fortemente che anche altri contesti basati su asset fossero esposti allo stesso errore di autorizzazione.
Questo problema è stato ragionevolmente classificato come Alto.
La classificazione dell'advisory era:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L
Tale classificazione ha senso.
L'affermazione non è che un attaccante non autenticato possa compromettere Plane da zero. L'affermazione è che qualsiasi normale utente autenticato può attraversare i confini dei tenant nel sottosistema asset V2 ed eseguire operazioni sugli asset ad alto impatto contro altri workspace.
Questa è una vulnerabilità di autorizzazione multi-tenant reale e difendibile.
Alcune persone sottovalutano i bug cross-tenant autenticati perché sentono:
"l'attaccante aveva già bisogno di un account"
Non è una difesa seria.
Nel software multi-workspace, gli utenti normali autenticati dovrebbero essere contenuti all'interno del proprio ambito di autorizzazione.
Se un utente con privilegi bassi nel workspace Bravo può leggere, copiare, eliminare o sovrascrivere oggetti nel workspace Alpha, allora l'isolamento dei workspace è rotto.
Questa è esattamente la proprietà di sicurezza che l'applicazione dovrebbe proteggere.
Soprattutto in una piattaforma di project management che memorizza contenuti di lavoro interni e asset di branding, questo è un problema significativo con un reale impatto sulla riservatezza e sull'integrità.
Il problema è stato corretto in Plane v1.3.1.
Le note di rilascio di v1.3.1 descrivevano chiaramente la correzione:
@allow_permission a tutti i metodi di WorkspaceFileAssetEndpointDuplicateAssetEndpoint ai workspace in cui il chiamante è un membro attivoQuesta è la direzione corretta per la correzione perché affronta entrambe le proprietà di sicurezza fallite:
Questo è esattamente ciò di cui questo bug aveva bisogno.
Una buona correzione qui non riguarda nascondere meglio gli UUID. Non riguarda cambiare la generazione degli URL presigned.
Riguarda il ripristino della regola corretta:
lo slug del workspace più l'UUID dell'asset non devono mai essere sufficienti senza un'autorizzazione limitata all'utente corrente
Questa è la parte che la patch ha ripristinato.
Questo problema è stato segnalato privatamente tramite GitHub Security Advisories.
Il rapporto includeva:
Il problema è stato successivamente pubblicato come:
L'advisory è stato pubblicato il 15 maggio 2026. La correzione è stata rilasciata in Plane v1.3.1.
La lezione chiave qui è semplice:
i sottosistemi di asset condivisi sono confini di autorizzazione, non solo aiutanti di storage
Molti sviluppatori pensano in termini di:
Queste cose sono dettagli implementativi.
La vera domanda di sicurezza è:
chi è autorizzato a risolvere, mutare, copiare o ricollegare quell'asset attraverso i confini dei tenant?
In Plane, quel confine non era applicato in modo coerente.
Questo è il vero insegnamento.
Questo bug rafforza anche qualcosa di importante riguardo alla revisione delle applicazioni multi-tenant:
Questa vulnerabilità non riguardava un comportamento di storage esotico.
Riguardava porre la giusta domanda sul confine di fiducia.
In Plane, un utente autenticato poteva fornire lo slug e gli UUID degli asset di un altro workspace, e il sottosistema asset V2 si fidava di quegli identificatori più di quanto avrebbe dovuto.
Ecco perché questo è diventato CVE-2026-46558.
Corretto in Plane v1.3.1.