
Links de Base Compartilhada do NocoDB Podem Convidar Membros Reais da Base e Sobreviver à Revogação de Compartilhamento
Links de Base Compartilhada do NocoDB Podem Convidar Membros Reais da Base e Sobreviver à Revogação do Compartilhamento
Encontrei esse problema ao revisar o NocoDB, com uma simples questão de segurança em mente:
Um link público de base compartilhada pode cruzar a fronteira do acesso temporário compartilhado para a associação real autenticada à base?
Neste caso, a resposta foi sim.
Uma sessão de base compartilhada autenticada apenas por xc-shared-base-id foi tratada como um visualizador normal da base para fins de ACL. Como as permissões de visualizador ainda alcançavam endpoints de gerenciamento de membros, um usuário com apenas o UUID da base compartilhada podia enumerar membros existentes da base e convidar um endereço de e-mail arbitrário para a base como membro real.
Esse usuário convidado podia então resgatar o convite através do fluxo normal de cadastro, obter uma conta autenticada padrão e manter o acesso à base mesmo depois que o proprietário desabilitasse o link de base compartilhada.
Esse problema se tornou CVE-2026-46552.
Projeto: NocoDB
Versão afetada validada: 0.301.3
Isso afetou o NocoDB; no site oficial, o NocoDB é apresentado como confiável por 35.000+ organizações, com 20+ milhões de downloads. O site também lista empresas como Accenture, Western Digital, Hyundai, Walmart, PwC, Bosch e American Express.
link público de base compartilhada -> xc-shared-base-id tratado como visualizador normal da base -> ACL de visualizador alcança endpoints de gerenciamento de membros -> atacante lista usuários da base e convida e-mail arbitrário -> usuário convidado resgata token de cadastro normal -> acesso autenticado durável à base sobrevive à revogação do link compartilhado
NocoDB é uma plataforma de colaboração orientada a banco de dados que expõe acesso à base via navegador, compartilhamento, gerenciamento de metadados e fluxos de trabalho de associação de usuários.
Isso significa que seu modelo de compartilhamento é uma fronteira de segurança real.
A questão importante aqui não era se links de base compartilhada podem ler conteúdo compartilhado.
A verdadeira questão era:
Um principal de compartilhamento público pode realizar ações que deveriam pertencer apenas a membros autenticados da base?
Neste caso, podia.
Recursos de compartilhamento público são fáceis de subestimar.
Isso é um erro.
Uma vez que um aplicativo suporta:
o principal risco não é apenas a exposição de dados.
O risco mais forte é o colapso de fronteira:
Esse era o verdadeiro problema aqui.
Isso não foi um bug na validação de login. Não foi um problema de falsificação de token. Não foi uma falha de redefinição de senha.
Foi uma clássica falha de fronteira de autorização:
Não abordei isso sondando endpoints aleatoriamente na esperança de que algo interessante respondesse.
O caminho mais forte foi identificar primeiro a fronteira de confiança de maior valor.
Para o NocoDB, essa era a fronteira entre:
Esses dois estados não deveriam ser intercambiáveis.
Um link de base compartilhada deveria representar acesso limitado, revogável e baseado em link. Não deveria ser capaz de criar novos principais de longa duração dentro da base.
Essa é exatamente a fronteira que falhou aqui.
A vulnerabilidade veio de como o acesso à base compartilhada foi integrado ao caminho normal de ACL.
No fluxo frontend da base compartilhada, xc-shared-base-id era injetado enquanto cabeçalhos normais de autenticação eram removidos.
Então, no backend, BaseViewStrategy aceitava xc-shared-base-id e traduzia o link compartilhado diretamente em roles / base_roles normais derivados da configuração da base compartilhada.
Esse foi o primeiro problema.
O segundo problema foi que permissões de nível de visualizador ainda incluíam ações de gerenciamento de membros.
Na camada de ACL, ProjectRoles.VIEWER podia alcançar:
baseUserListuserInviteEssas permissões guardavam rotas meta normais:
GET /api/v2/meta/bases/:baseId/usersPOST /api/v2/meta/bases/:baseId/usersPortanto, uma sessão de compartilhamento público era efetivamente autorizada a acessar endpoints de associação destinados a participantes reais da base.
O último passo estava no próprio fluxo de convite.
BaseUsersService.userInvite() verificava o poder da função e então criava:
invite_tokenE para sessões de base compartilhada:
invited_by tornava-se nullporque não havia uma identidade real de convidador autenticado por trás da requisição.
Essa é toda a cadeia do bug.
Porque a posse de um link de base compartilhada era suficiente.
O atacante não precisava de:
xc-authA cadeia de exploração era direta:
Isso converte compartilhamento de link revogável em associação durável.
A distinção importante é a persistência após a revogação.
Isso não era apenas:
"um visualizador podia chamar um endpoint de visualizador"
O principal vulnerável não era um visualizador autenticado normal.
Era uma sessão de compartilhamento público.
Isso importa porque o aplicativo tratava um principal transitório, limitado ao link, como se fosse confiável o suficiente para:
A verdadeira questão não era:
"Um usuário compartilhado pode ler dados compartilhados?"
A verdadeira questão era:
"O acesso de compartilhamento público pode ser convertido em acesso autenticado permanente que sobrevive à revogação do compartilhamento?"
A resposta foi sim.
É por isso que esta é uma vulnerabilidade real de autorização, e não apenas um comportamento surpreendente do aplicativo.
Validei isso localmente contra:
0.301.3dac49b0122c5ee655fb8f46a1b6e42dfeec1f3adhttp://127.0.0.1:8080A reprodução foi direta.
Primeiro, entrei como uma conta de proprietário normal, criei uma nova base, criei uma tabela e habilitei o acesso à base compartilhada como viewer:
PATCH /api/v2/meta/bases/<baseId>/shared
Content-Type: application/json
{
"roles": "viewer"
}
Isso retornou o UUID da base compartilhada.
Então, sem enviar nenhum xc-auth, usei apenas:
xc-shared-base-id: <sharedBaseUuid>
Usando apenas esse cabeçalho, chamei:
GET /api/v2/meta/bases/<baseId>/users
Isso retornou 200 OK e expôs membros reais da base, incluindo endereços de e-mail.
Ainda usando apenas xc-shared-base-id, chamei:
POST /api/v2/meta/bases/<baseId>/users
Content-Type: application/json
{
"email": "[email protected]",
"roles": "viewer"
}
Isso também retornou 200 OK.
Para validação local em laboratório sem entrega de e-mail, confirmei diretamente no banco de dados meta SQLite que:
nc_users_v2 continha o usuário convidado com um invite_token não nulonc_base_users_v2 continha uma linha real de associação para a base alvoinvited_by era NULLEntão resgatei o convite através do fluxo normal de cadastro:
POST /api/v2/auth/user/signup
Content-Type: application/json
{
"email": "[email protected]",
"password": "Password123.",
"token": "<invite_token>"
}
Usando o xc-auth retornado, chamei:
GET /api/v2/meta/bases/<baseId>/tables
Isso retornou 200 OK.
Finalmente, como proprietário, desabilitei o link de base compartilhada:
DELETE /api/v2/meta/bases/<baseId>/shared
Após isso:
xc-shared-base-id falhou com 401xc-auth normal ainda teve sucesso com 200200200200200200401200Isso estabeleceu a afirmação central de segurança:
Um único convite bem-sucedido de base compartilhada já teria sido suficiente para mostrar uma falha de autorização.
Mas a cadeia de validação completa importava por dois motivos.
Mostrou que não se tratava apenas de exposição de endpoint.
A sessão de compartilhamento público não apenas alcançou uma API restrita. Ela completou toda a cadeia de conversão de privilégio:
Provou que isso não era autorrevogável.
O impacto mais sério veio após a desabilitação do link compartilhado:
Isso é o que transformou acesso temporário por link em persistência de acesso durável.
Esta vulnerabilidade permite que qualquer pessoa com um link de base compartilhada:
O impacto principal é confidencialidade, porque um atacante pode manter acesso de leitura duradouro aos dados da base compartilhada através de uma conta autenticada comum.
Há também impacto na integridade, porque um principal de compartilhamento público pode modificar o estado de controle de acesso adicionando novos membros à base.
Isso é um resultado mais forte do que um vazamento de dados comum. É uma quebra de fronteira de privilégio entre compartilhamento anônimo e associação autenticada.
Este problema é razoavelmente classificado como uma falha de autorização entre escopos com impacto na confidencialidade.
CVSS:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
Esse vetor se encaixa no comportamento central aqui:
A direção da correção é direta.
Sessões de base compartilhada não devem herdar capacidades de gerenciamento de membros.
No mínimo:
baseUserList e userInvite de quaisquer permissões acessíveis através de xc-shared-base-idGET e POST /api/v2/meta/bases/:baseId/usersEste problema foi validado localmente contra NocoDB 0.301.3 no commit dac49b0122c5ee655fb8f46a1b6e42dfeec1f3ad.
O relatório demonstrou:
xc-shared-base-id para funções normais da baseO problema foi atribuído:
CVE-2026-46552
A lição principal aqui é simples:
acesso por link compartilhado não é a mesma coisa que associação confiável.
Muitos sistemas se metem em problemas quando colapsam essas duas ideias no mesmo modelo de função.
Um link compartilhado pode parecer operacionalmente semelhante a uma conta de visualizador, mas as suposições de confiança são diferentes:
Se esse principal de menor garantia pode realizar ações de gerenciamento ou criar novas identidades duráveis, a fronteira de compartilhamento já está quebrada.
Essa é a verdadeira lição.
Esta vulnerabilidade não era sobre contornar a autenticação completamente.
Era sobre colapsar dois níveis de confiança que deveriam ter permanecido separados.
No NocoDB, um link de base compartilhada deveria fornecer acesso temporário e revogável ao conteúdo compartilhado. Em vez disso, podia ser usado para enumerar membros, convidar um usuário real para a base e converter o acesso de compartilhamento público em associação autenticada durável que sobrevivia à revogação do compartilhamento.
É por isso que isso se tornou CVE-2026-46552.