Breach Watch — Have I Been Pwned integration
A partir da v4.6, o CipherVault verifica se passwords ou secrets expostos a usuários humanos aparecem em dumps de breach conhecidos via Have I Been Pwned — paridade com Keeper BreachWatch e Bitwarden HIBP integration.
Algoritmo k-anonymity
HIBP padrão. Plaintext nunca leak:
- SHA-1 hex uppercase do plaintext
- Apenas os 5 primeiros chars do hash saem do CV (
https://api.pwnedpasswords.com/range/<prefix>) - HIBP devolve todos os hashes que começam com esse prefix + count
- CV compara localmente o suffix restante — match → count > 0 → flag breach
A HIBP nunca vê o plaintext nem o hash completo. Trade-off correto: range API é unauthenticated, sem rate-limit, sem necessidade de key.
Configuração
Opt-in via env (default off por privacy conservatism e air-gap friendly):
export CV_BREACH_WATCH_ENABLED=true
Scheduler diário roda check em secrets ativos. Cache per-prefix 7 dias reduz outbound network significativamente.
Quando uso
| Caso | Útil? |
|---|---|
| Passwords humanos (login app, DB shared password) | ✅ Sim — dataset HIBP cobre |
API keys aleatórias (Stripe sk_live_..., etc.) | ⚠️ Marginal — random keys raramente em dumps |
| Tokens internos (JWT-style, OAuth) | ❌ Não — dataset HIBP é de password breaches |
Trade-off vs Keeper
Keeper BreachWatch usa dataset proprietário maior, com credenciais corporate-target. HIBP é open data + sem cost mas menos efetivo para credenciais não-leaked-publicamente.
Roadmap futuro: dataset adicional via DeHashed ou SpyCloud (paid). Fora scope v4.6.
Endpoints
GET /breach-watch/status Tenant config + last scan timestamp
GET /breach-watch/secrets Lista secrets com breach_count > 0
POST /breach-watch/check Manual check imediato em um secret_id
POST /breach-watch/dismiss Ack false-positive
UI
BreachWatchWidget reaproveitado em:
- Dashboard — count de secrets com breach + badge severity
- Profile — secrets pessoais comprometidos do usuário logado
- SecretCard — inline badge com count se > 0
Privacy / air-gap
- Outbound só pra
api.pwnedpasswords.com. Se outbound block: desabilita via env (não fica em estado degraded — feature inteira off). - Cache
_hibpCacheem memória — não persiste resultados HIBP. Restart limpa. - Audit log NÃO loga o prefix consultado (só "breach-watch-scan ran" sem detalhes).
Referências
- HIBP API docs
backend/src/lib/breachWatch.jsno repo do produto- Blog post v4.6