Skip to content

@audit segurança — Fluxo de Security Scan + Triagem

Extensão obrigatória do @audit segurança. SSOT do fluxo de Lovable Security Scan → triagem contra codebase → plano priorizado → execução.

Última atualização: 2026-05-07 · v1.0

Este doc é para auditoria automatizada de segurança (executa scan, analisa findings, gera plano). Para investigar uma vulnerabilidade já conhecida, use o checklist genérico em AUDIT.md Parte C (§11). Para o protocolo de migração de DB, use MIGRATION_SAFETY_PROTOCOL.


1. Quando invocar

Dispara o fluxo deste doc quando:

  • Usuário escreve @audit segurança ou pede explicitamente para "rodar scan", "analisar findings", "verificar segurança".
  • Pré-release de feature que toca auth, RLS, webhook, edge function pública.
  • Painel de Security mostra findings novos (ou após uma rodada de fixes, para validar).
  • Mudança em policy RLS, claims de JWT, política de webhook ou storage bucket.

Se o pedido é "corrigir um finding específico que eu já vi", não rode scan novo — vá direto para a etapa E3 (triagem) com o finding já em mãos.


2. Ferramentas disponíveis ao agente

FerramentaUso
security--run_security_scanDispara um novo scan (5 scanners). Leva ~1–2 min.
security--get_scan_resultsLê findings atuais. force=true se um scan estiver rodando.
security--get_table_schemaSchema do banco + prompt de análise (útil para correlacionar RLS).
supabase--linterLints programáticos do Postgres/Supabase (RLS desabilitada, search_path, etc.).
secrets--fetch_secretsConfirmar se um secret apontado como ausente existe de fato.
security--manage_security_findingmark_as_fixed / ignore / update_details. Sempre com justificativa.
security--update_memoryAtualizar a memória de segurança (o que é público intencional, riscos aceitos).

Os 5 scanners atuais:

  • supabase_lov — análise de RLS pelo agente Lovable (mais inteligente que o linter).
  • agent_security — análise de código (logs, fail-open, randomness, hardcoded secrets).
  • supabase — linter programático (search_path, security definer exposto, RLS habilitada sem policy).
  • connector_scan — integrações/conectores expostos.
  • dependency_auditbun audit (cobertura também via .github/workflows/audit.yml).

3. Fluxo passo a passo (5 etapas)

E1. Disparo

text
1. security--run_security_scan
2. Aguardar (poll com get_scan_results force=true) até "scanning" virar "completed".
3. Se findings > 20 → avisar usuário que vou quebrar a triagem em 2 turnos.

E2. Inventário

Para cada finding, registrar em tabela mental:

CampoOrigem
scanner_namesupabase_lov / agent_security / supabase / connector_scan / dependency_audit
internal_idÚnico — usado para mark_as_fixed / ignore
levelerror / warn / info
arquivo:linha apontadoextraído de details

E3. Triagem contra codebase

Para cada finding, executar:

  1. Ler o arquivo apontado (não a linha isolada — pelo menos ±30 linhas para entender contexto).
  2. Cruzar com regras do projeto:
    • Memórias mem://security/* (em especial fail-close-architectural-principle, rls-design-and-syntax-standards, payment-integration-security-standards, mural-otp-timing-safe-verification-standard).
    • ADRs em docs/architecture/adrs/.
    • SSOTs em docs/security/ (RLS_DESIGN_GUIDE, AUTHENTICATION, RLS_POLICIES).
  3. Classificar em uma de 4 categorias:
CategoriaCritérioAção
CRÍTICO real (P0)Vulnerabilidade explorável agora; nada mitiga upstream. Ex: privilege escalation em RLS, fail-open em webhook de pagamento sem outra validação.Plano imediato + 3-fases se for migration.
WARN real (P1/P2)Vulnerabilidade explorável mas com mitigação parcial (rate limit, log de auditoria, defesa em profundidade). Ex: Math.random em OTP com lockout progressivo.Plano numa próxima janela; documentar mitigação no doc.
Falso positivoO guard existe mas o scanner não enxerga. Ex: bypass via X-Gateway que na verdade é checado pelo Worker upstream antes de chegar; SECURITY DEFINER com guard interno (auth.jwt()->>'sub').manage_security_finding(operation: ignore, reason: ...) + update_memory com a regra para não reincidir.
Risco aceitoComportamento intencional documentado. Ex: bucket público porque serve avatares; RPC get_public_platform_config retorna apenas chaves whitelisted.ignore + memória What to not create vulnerabilities for.

Checklist de perguntas-pivô (rodar para cada finding antes de classificar)

  • [ ] Há guard upstream (Cloudflare Worker, edge function de auth) que o scanner não vê?
  • [ ] O secret apontado como ausente está de fato configurado? (cruzar com secrets--fetch_secrets)
  • [ ] A policy "permissiva" tem WITH CHECK ou guard via função SECURITY DEFINER interna?
  • [ ] O log apontado vaza dado real ou só metadado/comprimento (length=N)?
  • [ ] O endpoint "aberto" exige cookie HttpOnly/JWT validado depois (no body do handler) que o scanner não percebeu?
  • [ ] A tabela "sem SELECT policy" é propositalmente deny-all (ex: senha_historico)?
  • [ ] A função SECURITY DEFINER "executável por anon/authenticated" tem guard de portal/role no corpo (RAISE EXCEPTION se não for o caller esperado)?

E4. Plano priorizado

Output canônico para o usuário, antes de tocar em código:

markdown
## Sumário
- N findings analisados (X CRÍTICO, Y WARN, Z falsos positivos, W risco aceito)
- M scans / arquivos tocados

## Plano
| # | Finding | Categoria | Impacto | Correção | Esforço | Prioridade |
|---|---|---|---|---|---|---|
| 1 | privilege_escalation_usuario_papeis | CRÍTICO | School manager grants admin role | WITH CHECK papel_id IN (...) | Médio (migration 3-fases) | P0 |
| ... |

## Falsos positivos a marcar como ignorar
- `xgateway_burst_bypass`: motivo curto. Memória a atualizar: ...

## Aprovação
Quais itens você quer que eu execute agora? (P0 sempre recomendado)

Não execute nenhum fix antes da resposta do usuário.

E5. Execução (após aprovação)

Para cada item aprovado:

  1. Migrations RLSMIGRATION_SAFETY_PROTOCOL (Fase 1 textual → Fase 2 SQL+checklist → Fase 3 execução).
  2. Edge Functions → fail-close obrigatório, sanitização de logs (memory backend-error-sanitization), try/catch explícito (memory supabase-error-handling-pattern).
  3. Após validar fix com novo scanmanage_security_finding(operation: mark_as_fixed, explanation: ...).
  4. Se virou regra durável → criar memória em mem://security/* e atualizar mem://index.md.
  5. Documentar mudança no doc de SSOT correspondente (RLS_POLICIES, AUTHENTICATION, etc.) — sem doc atualizado, a entrega está incompleta (regra DOCUMENTATION_MAINTENANCE).

4. Padrões de remediação recorrentes (atalhos)

Sintoma do scannerSSOT da correção
RLS faltando escopo escola_id ou WITH CHECKRLS_DESIGN_GUIDE §WITH CHECK + cast ::text/::uuid
Webhook fail-open quando secret ausenteMemory payment-integration-security-standards — fail-close: if (!secret) return false
PII em log (CPF / telefone / JID)Mask helper já existente em supabase/functions/_shared/wasender-whatsapp.ts (telefone.slice(0,6) + '****')
Math.random() em OTPcrypto.getRandomValues(new Uint32Array(1)) — extrair generateSecureOTP() em _shared/otp-utils.ts
Privilege escalation em usuario_papeisEnum de papéis permitidos no WITH CHECK: papel_id IN (SELECT id FROM papeis WHERE nome IN ('coordenador', 'diretor', 'pedagogico', 'professor', 'marketing'))
Portal lendo sem filtro escola_idAdicionar AND (escola_id)::text = (auth.jwt()->>'escola_id')
Função SECURITY DEFINER exposta a anon/authenticatedAvaliar: (a) REVOKE EXECUTE FROM anon, authenticated se for interna, (b) manter exposta mas com guard RAISE EXCEPTION no corpo se for RPC pública.
senha_historico sem SELECT policyAdicionar policy explícita deny-all documentada (USING (false)) para deixar intent claro.
Cookie/JWT logado em texto puroSubstituir por presença + comprimento: 'Cookie: [present, length=' + h.length + ']'

5. Limites e quebra em múltiplos turnos

Quebrar em mais de 1 turno quando:

  • >15 findings densos — gera contexto demais.
  • Mudanças que tocam >3 RLS — cada migração precisa de seu próprio 3-fases.
  • Qualquer item que dependa de validação de RPC + edge function + frontend — 1 finding = 1 PR.
  • dependency_audit sugere bump de major — sair do @audit segurança e abrir tarefa de upgrade independente.

6. Anti-padrões (não fazer)

  • ❌ Aplicar fix antes de apresentar plano e receber aprovação.
  • mark_as_fixed antes de rodar novo scan que confirme remoção.
  • ignore sem update_memory correspondente — o scanner reincide.
  • ❌ Mexer em RLS sem 3-fases (regra crítica do projeto).
  • ❌ Tratar dependency_audit como bloqueante para release de feature — é contínuo (workflow audit.yml semanal).
  • ❌ Reescrever política RLS sem ler RLS_DESIGN_GUIDE antes.
  • ❌ Marcar finding como falso positivo sem ler ±30 linhas do arquivo apontado.

7. Output esperado (template)

Quando reportar ao usuário:

  1. Sumário executivo (3 linhas: total / CRÍTICOs / falsos positivos).
  2. Tabela do plano (formato §E4).
  3. Falsos positivos marcados com motivo e link para memória atualizada.
  4. Pergunta final: "Aprova execução de quais itens?".

Não despejar todo o JSON do scan no chat — sintetize.


Referências