Divulgação responsável de vulnerabilidades

Todo o software tem bugs. O nosso, preferimos que seja você a encontrar.

Este é o programa de divulgação de vulnerabilidades do diagnos. Não pagamos em dinheiro — hoje não temos como. Pagamos em gratidão pública, num lugar no hall da fama e na certeza de que o exame de alguém ficou mais seguro pelo seu contributo.

security.txt
curl https://diagnos.health/.well-known/security.txt Contact: mailto:[email protected]Contact: mailto:[email protected]Policy: https://diagnos.health/en/bounty/Preferred-Languages: pt-BR, en, es, it, frExpires: 2027-09-16T00:00:00Z

Se precisar de mais detalhes, o ficheiro está no ar: /.well-known/security.txt

Acesso rápido

As dez secções desta página, para abrir directamente a que procura.

Hall da fama

Toda a vulnerabilidade válida entra nesta lista, com o nome que escolher — o seu nome, a sua alcunha, o seu @ ou nenhum deles.

#InvestigadorO que encontrouQuando
001 VOCÊ esta linha está reservada quando quiser
002 — — —
003 — — —
004 — — —
005 — — —
Cartaz em pixel art de um homem de cartola a apontar o dedo a quem lê

PRECISO DE SI

PARA A SEGURANÇA DO DIAGNOS

Sim, está vazia. O programa nasceu com esta página, por isso alguém vai ter de ser o primeiro. Ainda não é uma vaga disputada.

Postura de segurança

O que já está em produção, e as seis lacunas que ainda não fechámos.

Controlos ativos em produção

  • A palavra-passe nunca chega até nós

    O início de sessão corre em OPAQUE (PAKE): o servidor nunca vê a sua palavra-passe, nem durante o login. Guarda só um registration_record, que sozinho não abre nada.

  • O servidor nunca abre o seu cofre

    As chaves nascem no seu dispositivo. O servidor só recebe texto cifrado — não existe uma linha de código do outro lado que abra uma KEK.

  • Repetir um pedido não funciona

    Todo o pedido sensível transporta nonce + timestamp, chave primária (scope_id, ts, nonce) no D1, tolerância de relógio de 120s e retenção de 300s, varrida por cron.

  • Cada pedido relevante vira registo

    Gravamos um objeto por pedido relevante no R2. A escrita é cobrada e corre fora do caminho crítico da resposta — auditar não atrasa ninguém.

  • O domínio mais sensível é o mais trancado

    sign.diagnos.health tem CSP default-src 'none' a sério — bloqueia, não só reporta — e SRI calculado no build. Cookie de dispositivo __Host-, HttpOnly, Secure, SameSite=Strict.

  • O dado clínico sabe onde mora

    Laudo e imagem ficam num bucket R2 com jurisdição UE amarrada diretamente ao binding — não é promessa em contrato, é configuração que a infraestrutura aplica.

Lacunas conhecidas

  • Nunca contratámos um teste de intrusão independente. Ninguém de fora auditou isto.
  • Não temos SOC 2 nem ISO 27001.
  • HIPAA: os requisitos técnicos estão cobertos, mas a cadeia de contratos com subprocessadores (BAA) está incompleta — só dois assinados, o resto em negociação.
  • A CSP da aplicação ainda está em modo report-only: reporta a violação, não bloqueia nada.
  • A varredura automatizada de vulnerabilidades ainda acontece de forma pontual, não como rotina contínua.
  • O disjuntor de rate limit é um palpite conservador, nunca calibrado contra tráfego real.

A primeira lista é o que já construímos. A segunda é a razão pela qual esta página existe. Não estamos a pedir a sua confiança — estamos a pedir a sua desconfiança, documentada num relatório.

Âmbito do programa

Os alvos autorizados, os que estão fora e a regra da audiência interna.

Nove alvos possíveis. A etiqueta ao lado de cada um diz se está dentro, fora, ou dentro mas com letra miúda — leia antes de apontar qualquer ferramenta a um deles.

Alvo Situação O que é
vault.diagnos.health Dentro do âmbito O servidor principal do produto — o "cofre". Sessão, destranque via OPAQUE, livro-razão, URLs assinados do R2, Agentes de IA, MCP e OAuth passam todos por aqui.
api.diagnos.health Dentro do âmbito O mesmo servidor, com o outro nome que o produto usa para ele. Hoje as duas entradas convivem no código — as duas valem.
/api/internal/v1/* Dentro, com reserva Prefixo dentro da própria API, reservado à aplicação oficial — exige cabeçalhos que um curl à solta não produz sozinho. Leia o aviso logo abaixo antes de testar esta linha.
sign.diagnos.health Dentro do âmbito A cerimónia de assinatura do laudo — WebAuthn/chave de acesso, aberta por hiperligação ou código QR. É o domínio mais sensível do produto.
app.diagnos.health Dentro do âmbito A aplicação web do diagnos.
diagnos.health Dentro do âmbito Este site, o que está a ler agora. Está no âmbito mesmo sendo marketing estático — mas ajuste a expectativa: o pior que há por aqui é um redirecionamento aberto.
SDK · CLI · API Apache-2.0 Dentro do âmbito SDK, CLI e API em Python, licença Apache-2.0. O código vai para um repositório público em breve — ler o código é bem-vindo.
*.diagnos.health Fora do âmbito Qualquer *.diagnos.health que não esteja nesta lista está fora do âmbito e fora do porto seguro. É o padrão consagrado pelo GitHub: só podemos autorizar pesquisa em sistema que é nosso.
cloudflare · google · modal · sentry · … Fora do âmbito Cloudflare, Google/Firebase, Modal, Sentry e afins. Reporte-lhes a eles, não a nós — a menos que o problema esteja claramente na nossa integração.

Sobre a linha "internal" (e porque o curl sozinho não chega lá)

Cabeçalhos exigidos

Os cinco cabeçalhos que a aplicação oficial emite sozinha.

A audiência internal exige, todos ao mesmo tempo:

  • Authorization: Bearer <Firebase ID token>
  • X-AppCheck-Token
  • X-Signature-Hmac
  • X-Signature-Nonce
  • X-Signature-Timestamp

O que não existe

Dois boatos internos que este parágrafo desfaz.
  • Não existe X-Device-Challenge. O nome circulou internamente, mas nunca existiu uma linha de código com ele.
  • Não existe bloqueio automático de workspace. Nenhuma chamada errada tranca uma conta sozinha — isto também circulou, e também é falso.

O que existe de facto

Limite de pedidos, antirreplay, travão de força bruta e telemetria revista por alguém.

O que existe de facto, e dá o mesmo recado:

  • Limite de pedidos por rota, e um disjuntor por âmbito: 600 pedidos por janela.
  • Antirreplay a sério: chave primária (scope_id, ts, nonce) — nonce repetido devolve 409, não 401.
  • Travão de força bruta no início de sessão: 10 tentativas em 15 minutos por conta, melhor esforço.
  • Todo 4xx/5xx vira sinal de segurança anónimo; os de gravidade alta abrem uma exceção que uma pessoa revê antes de qualquer bloqueio.

Teste a audiência internal pela aplicação web, com a sua própria conta: os cabeçalhos nascem sozinhos, e tudo o que fizer ali está dentro do âmbito e do porto seguro. Martelar /api/internal/v1/* direto no curl não prova nada além de uma coleção de 401 — e ainda gera ruído que alguém vai ter de triar à mão.

Dados de doentes

A única regra sem excepção: pare no primeiro registo real.

O que não fazer

  • Não abra o exame.
  • Não percorra o ecrã.
  • Não tire uma captura de ecrã.
  • Não copie o ID "para confirmar depois".

O que fazer

  • Reporte de imediato, com o mínimo necessário para provarmos que o problema existe.
  • A prova de conceito demonstra o acesso, nunca o conteúdo — por exemplo: "consegui listar registos de outros workspaces pelo endpoint X trocando o parâmetro Y", sem colar o laudo.
  • Apague toda a cópia local: cache, captura de ecrã, histórico do Burp, registo de proxy.
  • Nunca exfiltre, transfira, partilhe, publique ou tente monetizar dado de doente — nem para provar impacto.

Não é burocracia. É que do outro lado desse JSON está um resultado de biópsia com nome e apelido.

Regras de participação

O que pode durante o teste, uso de IA, prazo de resposta e divulgação.

Durante o teste

Contas de teste, ferramentas automatizadas, e pare ao primeiro dado real.
Pode
  • Testar com contas de teste próprias, ou contas criadas por si.
  • Usar ferramenta automatizada — scanner, fuzzer — com bom senso.
  • Parar ao primeiro sinal de dado de um doente real e reportar.
Não pode
  • Aceder, ou tentar aceder, à conta de outra pessoa.
  • Fazer DoS volumétrico, ou apontar um scanner a disparar milhares de pedidos por minuto contra produção — despejar tráfego não é investigação, é abuso.
  • Usar engenharia social contra a nossa equipa, os nossos doentes ou os nossos parceiros.
  • Fazer um ataque físico.

Parar não é sugestão — é a regra mais importante desta página. Detalhe completo em Dados de doentes.

Uso de IA em relatórios

Pode usar. Cada afirmação técnica do relatório continua a ser sua.
  • Pode usar IA para explorar ou escrever — não vamos fingir que isso não existe. Mas é responsável por cada palavra e cada afirmação técnica do relatório, gerada por IA ou não.
  • Diga explicitamente se uma ferramenta de IA ajudou.
  • Todo o relatório precisa de uma prova de conceito que funcione de verdade, reproduzida por si. Resultado de scanner ou de LLM sem confirmação manual não é uma vulnerabilidade — é uma hipótese, e uma hipótese sem verificação é fechada como inválida.

Relatório fabricado, exagerado ou com PoC que não reproduz é fechado sem resposta detalhada. A reincidência resulta em banimento do programa.

curl — jan. 2026

Em janeiro de 2026, o projeto curl encerrou por completo o seu programa de bug bounty depois de os relatórios gerados por IA passarem a superar em muito os relatórios válidos. Em anos de monitorização, nenhum relatório produzido só por IA, sem verificação humana, encontrou uma vulnerabilidade real.

Não queremos chegar lá.

Prazos de atendimento

Confirmação em até 5 dias úteis, depois triagem, correção e aviso.
  1. Confirmação

    Confirmamos a receção do seu relatório em até 5 dias úteis.

  2. Triagem

    Avaliamos a severidade e dizemos-lhe o encaminhamento.

  3. Correção

    Trabalhamos na correção com prioridade proporcional à severidade.

  4. Aviso

    Avisamos quando a correção for publicada.

  5. Reconhecimento

    Oferecemos crédito público opcional — e não retaliamos investigação de boa-fé.

A régua completa de severidade e prioridade está na secção Classificação de severidade.

São objetivos de atendimento, não garantia contratual de SLA — mas é o padrão que nos exigimos.

Divulgação pública

Pedimos 90 dias corridos antes de qualquer publicação.

Pedimos 90 dias corridos contados a partir da confirmação do problema — não do envio, que é uma data que só si controla — antes de qualquer publicação.

Se a correção sair antes disso, podemos combinar uma data conjunta mais cedo.

Se o problema estiver a ser explorado por terceiros neste momento, o prazo encolhe — avise-nos de imediato.

E nunca publique dado de doente, credencial real ou qualquer coisa que aumente o risco, mesmo depois do prazo.

Porto seguro jurídico

Por que esta política é a autorização expressa que o art. 154-A exige.

Na prática, comprometemo-nos a:

  • Não mover nem apoiar ação civil, participação-crime ou denúncia contra si pela pesquisa que fez dentro desta política — incluindo pelas medidas técnicas usadas para aceder a um sistema em âmbito.
  • Se um terceiro o ameaçar ou abrir ação contra si por essa pesquisa, declarar pública e formalmente que a sua conduta foi autorizada e de boa-fé.

E isto tem limite — tão visível quanto a promessa:

  • Vale só para os sistemas listados em Âmbito. Não podemos autorizar pesquisa num sistema de terceiros, mesmo que seja possível chegar lá a partir do nosso.
  • Não cobre conduta fora do âmbito nem fora das regras desta política.
  • Não cobre levar dados. Aceder para testar é uma coisa; extrair é outra — veja Dados de doentes e o §4.º do art. 154.º-A, que agrava a pena precisamente por isso.
  • Não vale para pesquisa feita para extorquir ou coagir alguém, nem para quem está excluído em Reconhecimento.

Não tem a certeza se um teste específico cabe nesta política? Pergunte antes. Fale connosco em [email protected].

Fundamento jurídico no Brasil

No Brasil não existem "CFAA" nem "DMCA". São leis norte-americanas, e colar essa sigla numa política brasileira não protegeria ninguém aqui — denunciaria só que o texto foi traduzido, e não pensado.

O que se aplica é o art. 154.º-A do Código Penal brasileiro (Lei n.º 12.737/2012, alterada pela Lei n.º 14.155/2021). Torna crime invadir dispositivo informático alheio "sem autorização expressa ou tácita" de quem utiliza esse dispositivo.

Há um pormenor que muda tudo. A redação de 2012 só se aplicava quando a invasão acontecia "mediante violação indevida de mecanismo de segurança" — era preciso quebrar uma proteção. A Lei n.º 14.155/2021 retirou essa exigência do texto. Hoje o crime já não depende de quebrar nada: depende apenas de agir sem autorização. A autorização passou a ser o elemento que decide tudo, sozinho.

É por isso que esta página é a autorização expressa de que a lei fala. E isso é mais forte do que prometer não o processar: com autorização, o crime nem chega a existir — não é uma defesa posterior ao facto, é a ausência de um dos elementos do próprio tipo penal. Uma conduta autorizada nunca se torna crime.

Achados não elegíveis

Os casos que encerramos sem análise, agrupados por categoria.

Não é que não nos importemos — é que sem impacto demonstrado não há como distinguir de ruído.

Configuração e cabeçalhos

Cabeçalho ausente, SPF/DKIM/DMARC, versão exposta.
  • Cabeçalho de segurança ausente (CSP, HSTS, X-Frame-Options) sem PoC de exploração real.
  • Registo SPF, DKIM ou DMARC ausente ou mal configurado.
  • Versão de software exposta em banner, header ou changelog público, sem exploração associada.
  • Ausência de certificate pinning numa aplicação móvel.

Interface e interação

Clickjacking sem ação sensível, self-XSS, redirect aberto.
  • Clickjacking numa página que não executa nenhuma ação sensível.
  • Self-XSS — a vítima precisa de colar o próprio payload.
  • Redirecionamento aberto sem impacto adicional demonstrado.

Enumeração e limites de taxa

Enumeração de utilizador, rate limit sem prova de brute-force.
  • Enumeração de utilizador ou e-mail — descobrir se existe um registo.
  • Ausência de rate limit sem prova de brute-force viável.
  • CSV injection sem execução comprovada no ambiente da vítima.

Infraestrutura e disponibilidade

DoS volumétrico e interceção sem falha nossa.
  • Negação de serviço volumétrica, ou que dependa de gerar tráfego massivo.
  • Ataque que exige intercetar tráfego de outra pessoa, sem uma falha nossa que o viabilize.

Terceiros e dependências

Falha numa biblioteca ou serviço que não operamos.
  • Falha numa biblioteca de terceiro, sem PoC de exploração específica no nosso ambiente.
  • Falha num serviço ou infraestrutura que não operamos.

Qualidade do relatório

Resultado de scanner ou de IA sem verificação humana.
  • Resultado de scanner sem PoC manual e sem confirmação de exploração real.
  • Relatório gerado por IA sem verificação humana e sem PoC reprodutível.

Fora do modelo de ameaça

Engenharia social, ataque físico, navegador obsoleto.
  • Engenharia social contra a nossa equipa, os nossos parceiros ou os nossos doentes.
  • Ataque físico contra escritório, funcionário ou dispositivo.
  • Bug que só se manifesta num navegador ou sistema operativo obsoleto, sem suporte do fabricante.
  • Ataque que depende de si seguir uma instrução do próprio atacante — colar um comando, instalar uma extensão.

Acha que o seu caso é a exceção? Envie-o na mesma e explique porquê. Esta lista é um filtro, não um muro.

Classificação de severidade

Crítica, alta, média e baixa, com exemplos concretos do produto.

A severidade decide uma coisa: a ordem da fila de correção. Mais nada.

Severidade Critério geral Exemplos no diagnos
Crítica Compromete a confidencialidade de mais do que um doente, ou quebra a garantia central do fim-a-fim — sem ser preciso a vítima clicar em nada.
  • Decifrar o relatório de alguém sem ter a chave — a quebra do próprio modelo de ponta-a-ponta
  • Bypass de autenticação que atravessa workspaces
  • Extração de material de chave do nosso backend
  • Execução remota de código no servidor que processa os exames
  • IDOR que cruza workspaces diferentes
Alta Compromete dados de um único workspace, ou dá privilégio de administrador dentro dele — ainda sem interação da vítima.
  • IDOR dentro do mesmo workspace
  • Escalada para administrador de um workspace
  • XSS armazenado numa área autenticada
  • Bypass pontual do WebAuthn
Média Tem impacto real, mas limitado: precisa de um clique da vítima, ou expõe metadados em vez do conteúdo do relatório.
  • XSS refletido que precisa de um clique da vítima
  • CSRF numa ação que não é clínica
  • Fuga de metadados que confirma que um exame existe, sem revelar o conteúdo
Baixa Impacto mínimo, exige condições raras a acontecer todas ao mesmo tempo, ou é apenas informação — sem caminho claro até um dado de doente.
  • Erro verboso que não expõe segredo nenhum
  • Versão de biblioteca exposta, sem CVE explorável

A classificação final é nossa — mas explicamos o raciocínio. Se discordar, diga: reavaliamos.

Reconhecimento e elegibilidade

Não há pagamento em dinheiro. O que existe, e quem pode receber.

Quatro coisas, por esta ordem — a primeira dói um pouco.

  1. Dinheiro: zero.

    Sem "estamos a avaliar". Zero, mesmo. Somos uma equipa pequena, e o dinheiro que existe paga servidor e pessoas. Se isso mudar um dia, esta página muda também — e fica a saber entre os primeiros.

  2. Crédito de produto, talvez.

    Podemos — ao nosso critério e sem qualquer obrigação — oferecer crédito de utilização da plataforma. Sem valor combinado, sem garantia, não é negociável. Não é pagamento: é gratidão com uma fatura por perto.

  3. Um lugar no hall da fama.

    Toda a vulnerabilidade válida entra — com o nome escolhido por si: nome verdadeiro, alcunha, @ de rede social ou anónimo.

    Ver o hall da fama
  4. A gratidão de quem nunca vai conhecer.

    Do outro lado está o médico e o doente que nunca vão saber o seu nome. É pouco. Sabemos que é pouco. Mas é verdade.

E pedimos uma coisa em troca: licença para citar o seu relatório — técnico, sem dado de doente — no nosso changelog de segurança, quando a correção for publicada.

Quem pode participar

Qualquer pessoa pode reportar, e corrigimos da mesma forma. O que muda é o crédito — sem reconhecimento público nem crédito de produto para:

  • Quem trabalha ou trabalhou na MedDeck nos últimos seis meses — prestadores de serviço incluídos.
  • Familiar direto de quem tem informação privilegiada sobre o sistema testado.
  • Pessoa ou entidade em lista de sanções (OFAC/SDN, União Europeia) ou em país sob embargo abrangente.
  • Quem chegou até à falha por quebra de contrato ou fuga de informação interna, e não por pesquisa independente.

Como enviar um relatório

Os dois canais, criptografia e o que o relatório precisa de conter.

A maior parte dos relatórios entra pela caixa padrão. A outra existe para quando esperar custaria caro a sério.

O canal padrão

[email protected]

Todo o relatório entra por aqui — é a caixa que lemos primeiro, sempre.

Enviar relatório

Só quando esperar custa caro

[email protected]

Exploração ativa a acontecer agora. Dados de um doente já expostos publicamente. Credencial comprometida. Esta caixa é para isso — e só para isso.

Usar esta caixa para avisar que falta um cabeçalho de segurança é puxar o travão de emergência para sair na paragem certa: funciona, mas toda a gente na carruagem vai olhar para si.

Isto não pode esperar

O que o relatório precisa de conter

  • Passos de reprodução numerados, pela ordem em que os fez.
  • O impacto real — o que um atacante consegue FAZER, não só "consegui X".
  • Ambiente, navegador e conta que utilizou.
  • Uma prova de conceito mínima e não destrutiva.

Não precisa de estar em inglês, nem formatado como CVE. Clareza vale mais do que formalismo.

Mantenha tudo no canal privado connosco até combinarmos juntos a divulgação pública.

O ficheiro que faz este trabalho por si. Já está no ar, e é por ele que uma ferramenta automática nos encontra antes de qualquer humano ler isto: /.well-known/security.txt

Relatório cifrado

Ainda não publicámos uma chave PGP. Quer cifrar o relatório mesmo assim? Peça-nos por e-mail que enviamos uma forma de o fazer.

Perguntas frequentes

Oito respostas directas, do pagamento ao prazo de divulgação.

Pagam mesmo nada?

Nada. Nem em dinheiro, nem em cripto, nem em t-shirt. Podemos oferecer crédito de produto quando fizer sentido, sem qualquer garantia — é gratidão com limite, não um preço disfarçado.

Posso testar com a minha conta a sério?

Pode, e é o modo recomendado para quem é da audiência interna — veja a secção "Âmbito". O que nunca pode, em hipótese nenhuma, é testar com a conta de outra pessoa.

Encontrei dados de um doente. E agora?

Pare. Não abra o exame, não percorra, não copie o ID "para confirmar depois". Reporte o achado sem colar o conteúdo do relatório — a secção "Dados de doentes" tem o passo a passo, e não é burocracia: é a diferença entre investigação de segurança e crime.

Quanto tempo até alguém me responder?

Confirmamos a receção em até 5 dias úteis; depois, recebe uma posição sobre a gravidade e o encaminhamento. É a meta de atendimento a que nos obrigamos, não uma cláusula de SLA contratual.

Posso publicar o que encontrei?

Sim — 90 dias corridos depois da confirmação do problema, ou antes se combinarmos uma data em conjunto. Nunca com dados de doentes lá dentro, mesmo depois do prazo.

Usei IA para encontrar isto. Há problema?

Nenhum, desde que tenha verificado e reproduzido o problema você mesmo, num ambiente real. Uma saída de IA sem essa verificação não é uma vulnerabilidade, é uma hipótese — a secção "Regras" explica porquê.

Vão processar-me?

Não, se seguiu esta política. A secção "Porto seguro" é, numa frase, a autorização expressa que o art. 154.º-A do Código Penal brasileiro exige para aquilo que está prestes a fazer não ser crime — não é retórica, é o texto da lei.

Já reportei e não obtive resposta.

Reenvie mencionando a data do primeiro envio — o e-mail perde-se. Se for mesmo urgente, use a caixa de urgência. Não é desconsideração: somos uma equipa pequena, não um centro de operações de segurança 24 horas.

É isto. Pode começar.

Se leu até aqui, já se importa com os dados destes doentes mais do que muita gente que trabalha com eles todos os dias. Obrigado — e boa caçada.

Reportar uma falha