fix(agents): POST /agents nunca verificava tenant de userId/extensionId
Achado numa revisão de segurança sobre o trabalho da PHASE 29: um FK do Postgres só checa que a linha referenciada existe, não que ela é visível sob a RLS da sessão atual — então um userId/extensionId de outro tenant seria aceito silenciosamente no create do Agent (violação do princípio já seguido em todo o resto do código: nunca confiar em id vindo do client sem checar contra o tenant do JWT). O frontend já só oferece opções do próprio tenant, mas isso é conveniência de UI, não autorização. Corrigido com uma checagem explícita de TenantMembership/Extension antes do create (400 se não pertencer). Reverificado ponta a ponta: criação legítima continua funcionando igual. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
This commit is contained in:
17
TODO.md
17
TODO.md
@@ -1006,6 +1006,23 @@ Troncos, Discador > Lista de Bloqueio (agente.md secao 50-51, 41-42, 71,
|
||||
`bridge(${destination_number})` → gerar v1 (DRAFT) → ativar → badge
|
||||
"Ativa" confirmado. Smoke test de regressão nas 13 telas anteriores
|
||||
do tenant + platform, todas 200 sem quebrar nada.
|
||||
- [x] **Bug real de segurança, achado numa revisão dedicada depois desta
|
||||
fase (PHASE 31)**: `POST /agents` nunca verificava que
|
||||
`dto.userId`/`dto.extensionId` pertencem ao tenant de quem está
|
||||
chamando — um FK do Postgres só checa que a linha existe, não que
|
||||
ela é visível sob a RLS da sessão atual, então um `userId`/
|
||||
`extensionId` de **outro tenant** seria aceito silenciosamente
|
||||
(secao 31/146: nunca confiar em id vindo do client sem checar
|
||||
contra o tenant do JWT — o frontend já só oferece opções do próprio
|
||||
tenant, mas isso é conveniência de UI, o backend é a autoridade).
|
||||
Corrigido com uma checagem explícita de `TenantMembership`/
|
||||
`Extension` antes do create, 400 se não pertencer. Impacto prático
|
||||
limitado (precisaria adivinhar um UUID de outro tenant, e o agente
|
||||
criado ficaria órfão/inerte — o usuário referenciado nunca teria
|
||||
`tenantId` ativo igual ao do agente sem ter membership de verdade),
|
||||
mas corrigido de qualquer forma por princípio arquitetural.
|
||||
Reverificado ponta a ponta depois da correção: criação legítima
|
||||
continua funcionando igual.
|
||||
- [ ] Sem paginação/uniqueness real em `Agent.userId`/`extensionId` — o
|
||||
"só quem não é agente ainda" é conveniência de UI, não constraint de
|
||||
banco (mesma classe de lacuna sistêmica da PHASE 12, `@@unique` +
|
||||
|
||||
Reference in New Issue
Block a user