
O subsistema de ativos do Plane V2 confiava em slugs de workspace e UUIDs de ativos sem aplicar as verificações de associação corretas, o que permitia que um usuário autenticado lesse, copiasse, excluísse e sobrescrevesse ativos em outros workspaces.
O subsistema de ativos V2 do Plane confiava em slugs de workspace e UUIDs de ativos sem aplicar as verificações de associação corretas, o que permitia que um usuário autenticado lesse, copiasse, excluísse e sobrescrevesse ativos em outros workspaces.
Encontrei este problema ao revisar o Plane, a plataforma de gerenciamento de projetos de código aberto, com uma pergunta muito específica em mente:
Os endpoints de ativos V2 realmente aplicam limites de workspace ou confiam demais em slugs de workspace e IDs de ativos fornecidos pelo atacante?
Neste caso, a resposta foi não.
O subsistema de ativos V2 do Plane expôs duas falhas de autorização relacionadas que quebraram o isolamento do workspace para qualquer usuário autenticado:
Isso tornou possível o abuso de ativos entre workspaces.
No meu PoC validado, um usuário normal no workspace Bravo foi capaz de:
Esse problema foi posteriormente atribuído CVE-2026-46558.
Plane: Plane no GitHub
CVE: CVE-2026-46558
Isso afetou o Plane, que em seu site oficial é apresentado como sendo usado por mais de 50.000 equipes em todo o mundo. O Plane também destaca forte adoção de código aberto, incluindo mais de 46.000 estrelas no GitHub e mais de 1.000.000 de pulls no Docker, e exibe organizações como Tencent, Accenture, Microsoft e Amazon.
atacante autenticado no workspace B → rota de ativo V2 no nível do workspace confia no slug do workspace de destino e no UUID do ativo sem verificações de associação adequadas → leitura / patch / exclusão pré-assinados contra ativos do workspace A + a pesquisa de fonte de duplicação de ativos confia no UUID de origem carregado → divulgação, cópia, exclusão e sobrescrição de branding entre workspaces
Plane é uma plataforma de gerenciamento de projetos de código aberto usada para gerenciar:
Isso significa que seu subsistema de ativos está em um limite de confiança real.
A questão importante aqui não era se o Plane suporta uploads.
A verdadeira questão era:
O Plane aplica o isolamento do workspace quando um usuário autenticado referencia ativos pertencentes a outro workspace?
Neste caso, não aplicava.
Muitas revisões de aplicativos multi-inquilino focam primeiro em endpoints administrativos óbvios ou atualizações diretas de configurações.
Isso perde uma classe de bug muito comum e muito real:
acesso secundário a objetos por meio de sistemas de arquivos ou ativos compartilhados
Sistemas de ativos são fáceis de errar porque frequentemente combinam:
Esse é exatamente o tipo de lugar onde os limites do inquilino enfraquecem silenciosamente.
Este problema não era sobre corrupção de armazenamento. Não era sobre o S3 em si. Não era sobre manipulação de MIME de upload.
Era uma falha de limite de autorização:
Isso é suficiente para criar uma vulnerabilidade real.
Não abordei o Plane cegamente fuzzeando endpoints aleatórios ou adivinhando UUIDs sem modelo.
A abordagem mais forte foi identificar primeiro o limite de isolamento mais promissor.
Para o Plane, esse era o subsistema de ativos V2.
Por quê?
Porque um sistema de ativos compartilhado se torna perigoso quando:
Esse era o limite certo a inspecionar.
E foi exatamente onde o bug vivia.
Isso era, na verdade, duas falhas de autorização relacionadas no mesmo subsistema.
As rotas de ativos no nível do workspace foram expostas através de:
apps/api/plane/app/urls/asset.py:50-56Os manipuladores vulneráveis estavam em:
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:409O problema era simples.
WorkspaceFileAssetEndpoint aceitava um slug de workspace e um UUID de ativo, depois resolvia objetos diretamente como:
workspace = Workspace.objects.get(slug=slug)
e:
asset = FileAsset.objects.get(id=asset_id, workspace__slug=slug)
sem primeiro garantir que o chamador era realmente um membro autorizado daquele workspace de destino.
Isso significava que o endpoint ainda podia:
para objetos de outro workspace.
A rota de duplicação de ativos foi mapeada através de:
apps/api/plane/app/urls/asset.py:100-101A lógica vulnerável estava em:
apps/api/plane/app/views/asset/v2.py:736-780O workspace de destino tinha um decorador de autorização. Mas a consulta do ativo de origem não tinha.
O objeto de origem foi carregado com:
original_asset = FileAsset.objects.filter(id=asset_id, is_uploaded=True).first()
Isso significava que o chamador só precisava:
Não havia verificação de que o chamador pertencia ao workspace de origem que realmente possuía aquele ativo.
Esse é todo o segundo bug.
A distinção importante é o impacto entre workspaces.
Muitos bugs de autorização são minimizados como:
"ainda requer login"
Isso perde o ponto.
A verdadeira questão não é:
"O chamador está autenticado?"
A verdadeira questão é:
"O chamador está autorizado para o workspace específico e o ativo específico que está sendo manipulado?"
No Plane, a resposta era não.
Isso transforma o que pode parecer um tratamento comum de objetos em um problema real de segurança multi-inquilino.
Há uma clara diferença entre:
Este problema era firmemente o segundo caso.
Validei o problema localmente contra o Plane Community Edition 1.2.3 usando dois usuários comuns em dois workspaces não relacionados:
alpha-20260323072017bravo-20260323072017Usei Alpha para criar um ativo carregado privado legítimo em um problema de projeto.
O ID do ativo privado validado na minha execução foi:
6ed6ed62-d1b2-4399-8220-336c01b7d72c