JustCyber

ThreatRadar LATAM

O boletim de CVE do dia tem trezentas linhas e três delas tocam a sua pilha.

ThreatRadar parte de um perfil de superfície que o cliente declara — tecnologias, fornecedores e setores — e usa esse perfil para separar o que importa do que é ruído. A correlação é determinística e auditável: interseção de tecnologias, casamento de fornecedor por substring, e uma regra explícita de que vulnerabilidade crítica entra na fila mesmo sem casar tecnologia. O motivo do casamento fica gravado em texto no próprio match.

A arquitetura é de fan-out: as fontes públicas são globais, mas cada item é materializado por tenant, sob a RLS do tenant, com upsert idempotente por (tenant, tipo de fonte, id externo). Assim o cliente vê a sua cópia correlacionada ao seu perfil, e o isolamento não depende de filtro de aplicação.

O que está pronto é a leitura do feed, a fila de triagem com transições validadas, o perfil e o brief executivo por IA. Mas sem ingestão essas três primeiras só têm conteúdo onde o seed de demonstração colocou um CVE e um match: num tenant novo o feed nasce vazio e continua vazio, e o perfil de superfície é a única parte que o cliente exercita de ponta a ponta hoje. O brief é honesto por desenho: é marcado como rascunho, se ancora só no conteúdo do item e, quando o guardrail barra, devolve `blocked` com resumo nulo em vez de inventar texto. O que ainda não anda é a ingestão: o pedido de coleta é emitido no outbox e nenhum consumidor está registrado no relay, e o parser de feed é genérico demais para os formatos reais das fontes.

O que faz hoje

Capacidades em operação

Cada item corresponde a funcionalidade que existe no código e é alcançável por um usuário com o escopo correto.

  • Perfil de superfície do tenant

    GET e PUT /threatradar/profile com tecnologias, fornecedores e setores, normalizados e deduplicados, uma linha por tenant com upsert idempotente.

  • Feed com filtros

    GET /threatradar/feed com filtro por severidade, CVE, tecnologia afetada e data, paginado por cursor. Detalhe por item com CVEs, tecnologias, publicação e resumo.

  • Correlação determinística e explicável

    Score 0-100 pela banda de severidade mais bônus por casamento (10 para tecnologia, 5 para fornecedor). Item sem casamento e não-crítico simplesmente não vira match — a regra existe para reduzir falso positivo.

  • Fila de triagem

    GET /threatradar/matches com filtro por status e risco mínimo, item embutido no retorno. PATCH com transições validadas: confirmed e dismissed são terminais.

  • Brief executivo por IA

    POST /threatradar/items/{id}/brief gera até cinco frases em PT-BR sobre o que é a ameaça, a quem afeta, a urgência e a ação de maior impacto. Grava em `summary_pt`, devolve `is_draft: true` e aceita Idempotency-Key para o duplo clique não gastar duas vezes.

  • Conteúdo de feed tratado como hostil

    Título e resumo de terceiro entram embrulhados em `wrap_untrusted`; o corpo do feed passa por redação de segredo na ingestão. O prompt proíbe inventar CVE ou CVSS além do fornecido.

  • Coletor SSRF-safe

    Coletor SSRF-safe (escrito, ainda não ligado) — quando a ingestão for conectada ao relay, o coletor resolve o host da fonte antes de conectar e recusa IP privado, loopback ou de metadata; conexão pinada ao IP validado, sem seguir redirect, teto de 1 MB por fonte, orçamento de tempo total e contrato no-raise. / Fan-out por tenant (escrito, ainda não ligado) — upsert idempotente de itens e de matches por tenant, com contagem de novos itens, novos matches e alertas por execução, e trilha em audit_log. Nenhum dos dois é executado hoje: o consumidor do pedido de coleta não está registrado no relay.

  • Fan-out por tenant

    Upsert idempotente de itens e de matches por tenant, com contagem de novos itens, novos matches e alertas por execução, e trilha em audit_log.

O que fica com você

Entregáveis

  • Telas /app/threatradar (feed), /app/threatradar/triagem (fila de matches), /app/threatradar/perfil e /app/threatradar/item/[id] com o brief.
  • Perfil de superfície persistido por tenant.
  • Fila de matches com score, motivo do casamento e estado de triagem.
  • Resumo executivo em PT-BR gravado no item, marcado como rascunho de IA.

O que este módulo não faz

A coleta não roda hoje. O tópico `threatradar.refresh.requested` não tem consumidor registrado no relay do outbox (`_enqueue` em app/worker/tasks/outbox.py trata scan, shadowsignal, soc, triageai, securecode, otsentinel, orchestrator, casos e hibp — não trata threatradar). Manual e agendado emitem o evento e nada é enfileirado; a task `threatradar.refresh` existe e nunca é chamada. Consequência de cobrança: o refresh manual reserva crédito no `start_refresh` e o capture/release vive dentro de `execute_refresh`, então o hold fica aberto. Além disso, o parser de feed é genérico (JSON plano com id, title, severity) e não há adaptador para o formato do NVD 2.0, do CERT.br ou de feeds de IOC — a fonte demo do seed aponta para a API do NVD e não é decodificada. Não há catálogo de fontes globais além dessa fonte demo, e `threatradar_sources` é control-plane sem endpoint de gestão. O alerta `threatradar.alert.raised` é gravado no outbox e não tem consumidor: não vira e-mail nem notificação. Não há tabela de run — o `run_id` devolvido é o id do hold — e não há reaper. O brief consome token do provedor sem hold de créditos e é sob demanda, um item por chamada. O beat agendado só roda com `JC_THREATRADAR_ENABLED=true`, que é false por padrão. O rótulo LATAM descreve a intenção do recorte regional: hoje o produto é o perfil mais a correlação, sem fonte regional ligada.

Declaramos o limite porque software de segurança que promete tudo não é auditável. Se o que falta aqui é o que você precisa, o serviço consultivo cobre — ou dizemos que não cobre.

Conecta com

  • app/scan/passive (guard SSRF e redação de segredo)
  • app/ai (AiGateway, registry aditivo, sanitize)
  • app/billing (hold no refresh manual)
  • app/core/outbox e worker Celery (beat de sweep; consumidor de refresh não registrado no relay)
  • telas /app/threatradar, /triagem, /perfil e /item/[id] no app web

Controle de acesso

O acesso é concedido por escopo, não por perfil genérico. Quem só precisa ler não recebe permissão de escrita, e a barreira é o banco de dados, não a interface.

  • threatradar:feed:read
  • threatradar:feed:write
  • threatradar:profile:read
  • threatradar:profile:write
  • threatradar:collect:run
ThreatRadar LATAM

Quer ver funcionando?

Demonstração com dado do seu ambiente, não com base de exemplo. É a única forma de saber se serve.