Uma API Inocente, Um Identificador Nada Inocente
Imagina a cena: você abre o Tor Browser, clica em “Nova Identidade”, muda o circuito, limpa cookies, histórico — tudo. Pronto, agora você é uma pessoa diferente na internet. Certo?
Errado. Uma vulnerabilidade descoberta pela Fingerprint.com mostrou que uma simples chamada à API indexedDB.databases() podia gerar um identificador único, determinístico e estável que sobrevivia a tudo isso. Durante toda a sessão do navegador, qualquer site podia te rastrear — mesmo no modo privado, mesmo no Tor, mesmo depois de trocar de identidade.
O bug recebeu o CVE-2026-6770 e foi corrigido no Firefox 150 e ESR 140.10.0, lançados em 21 de abril de 2026. Mas o estrago conceitual já está feito. E a pergunta que fica é: quantas vulnerabilidades parecidas ainda existem escondidas nas entranhas dos nossos navegadores?
Como o IndexedDB Funciona (e Onde Ele Quebra)
O IndexedDB é uma API de armazenamento no navegador. Diferente do localStorage, ele suporta bancos de dados complexos com índices, transações e armazenamento binário. Cada origem (domínio) tem seu próprio espaço isolado — pelo menos, é assim que deveria funcionar.
O problema está no método indexedDB.databases(), que retorna uma lista com os nomes dos bancos criados naquela origem. Em teoria, a ordem dessa lista não deveria importar. Na prática, ela importa demais.
No Firefox, internamente, os nomes dos bancos são mapeados para UUIDs usando uma hash table global:
StorageDatabaseNameHashtable = nsTHashMap<nsString, nsString>
StaticAutoPtr<StorageDatabaseNameHashtable> gStorageDatabaseNameHashtable
O detalhe crítico: essa hash table é compartilhada entre todas as origens e usa um seed aleatório gerado uma vez na inicialização do processo do navegador. O seed nunca muda até você fechar completamente o Firefox.
A Mecânica do Ataque
Quando um site chama indexedDB.databases(), o Firefox executa internamente o QuotaClient::GetDatabaseFilenames() dentro de GetDatabasesOp::DoDatabaseWork(). Os nomes dos bancos são inseridos em um nsTHashSet. E aqui está o problema: nenhuma ordenação é feita antes de retornar o resultado. A ordem final depende do layout interno dos buckets da hash table.
Como o seed é o mesmo para todo o processo, a fórmula fica algo como:
UUID = HASH(seed || origin || database_name)
Dois sites completamente diferentes, criando bancos com os mesmos nomes, vão observar exatamente a mesma ordem nos resultados. Isso porque o seed é compartilhado, e as colisões na hash table são determinísticas.
Na prática, o ataque funciona assim:
| Passo | Ação | Resultado |
|---|---|---|
| 1 | Site A cria bancos “1”, “2”, “3”, “4”, “5” | Bancos armazenados na hash table global |
| 2 | Site A chama indexedDB.databases() |
Retorna [3, 1, 5, 2, 4] (ordem dos buckets) |
| 3 | Site B (outra origem) cria os mesmos bancos | Mesma hash table, mesmo seed |
| 4 | Site B chama indexedDB.databases() |
Retorna [3, 1, 5, 2, 4] — idêntico |
| 5 | Ambos os sites compartilham o identificador | Rastreamento cross-origin estabelecido |
Cinco bancos com nomes simples já geram entropia suficiente para criar um identificador único. Adicione mais nomes e a capacidade de encoding aumenta exponencialmente.
Por Que o Tor Browser É o Alvo Mais Crítico
O Firefox comum já tem um problema sério aqui. Mas o Tor Browser transforma isso em um pesadelo.
O Tor Browser é construído sobre o Firefox ESR. Ele herda toda a engine Gecko, incluindo a implementação do IndexedDB. E o recurso “Nova Identidade” — aquele botão que deveria ser o reset nuclear da sua sessão — não reinicia o processo do navegador. Ele limpa cookies, histórico, cache, altera o circuito Tor… mas o processo Firefox continua rodando. O seed da hash table permanece intacto.
Eu já vi gente argumentar que “ah, mas é só reiniciar o browser”. Verdade. Mas o ponto é que o Tor Browser vende a promessa de que “Nova Identidade” é equivalente a reiniciar. Milhares de ativistas, jornalistas e dissidentes confiam nesse botão. E durante anos, ele não fazia o que prometia — pelo menos não contra esse vetor.
Para colocar em perspectiva:
| Cenário | O Identificador Sobrevive? |
|---|---|
| Navegar em sites diferentes no mesmo tab | Sim |
| Abrir navegação privada, fechar, abrir de novo | Sim |
| Tor Browser → “Nova Identidade” | Sim |
| Fechar o navegador completamente e reabrir | Não |
Só o encerramento total do processo limpa o seed. Qualquer coisa menos que isso mantém o identificador ativo.
O Código da Prova de Conceito
A Fingerprint.com publicou o conceito do ataque. Não é complicado — na real, é assustadoramente simples:
// Cria bancos de dados com nomes previsíveis
const dbNames = ['1', '2', '3', '4', '5', '6', '7', '8'];
for (const name of dbNames) {
const request = indexedDB.open(name, 1);
await new Promise((resolve, reject) => {
request.onsuccess = resolve;
request.onerror = reject;
});
}
// Enumera os bancos e captura a ordem
const databases = await indexedDB.databases();
const fingerprint = databases.map(db => db.name).join(',');
// 'fingerprint' agora é algo como "3,1,5,2,4,8,6,7"
// Esse valor é IDÊNTICO em qualquer site durante a mesma sessão
console.log('Identificador do processo:', fingerprint);
Menos de 15 linhas de JavaScript. Nenhuma permissão especial. Nenhum pop-up pedindo autorização. Funciona silenciosamente em qualquer página que rode JavaScript.
A Ironia: Quem Descobriu Foi Uma Empresa de Fingerprinting
Esse é talvez o detalhe mais delicioso de toda a história. A Fingerprint.com é, literalmente, uma empresa que vende soluções de identificação de dispositivos. Eles ganham dinheiro fazendo fingerprinting de browsers para prevenção de fraude.
Na discussão do Hacker News, isso gerou uma debate acalorado. Alguns argumentaram que é hipocrisia — uma empresa de rastreamento fazendo responsible disclosure de uma vulnerabilidade de rastreamento. Outros defenderam que, independente do modelo de negócio, a divulgação responsável beneficia todos.
Um representante da Fingerprint.com (valve1) afirmou que a empresa não usa vulnerabilidades nos seus produtos comerciais. Mas como um comentarista (mtlynch) apontou: “Todo fingerprinting explora comportamento não intencional do software. Nenhum software quer ser fingerprinted.”
A discussão levanta uma questão filosófica real: existe fingerprinting “ético”? Ou toda forma de identificação de dispositivo sem consentimento explícito é, por definição, uma exploração?
Eu tendo a achar que a divulgação foi a coisa certa, independente de quem fez. Melhor que a Fingerprint.com publique isso do que algum ator estatal use em silêncio por mais cinco anos.
O Fix: Surpreendentemente Simples
A correção da Mozilla foi quase constrangedoramente simples: ordenar os resultados antes de retorná-los.
Quando indexedDB.databases() é chamado, ao invés de iterar diretamente sobre os buckets da hash table (expondo a ordem interna), o Firefox 150 agora ordena a lista alfabeticamente antes de devolver ao JavaScript. Isso elimina toda a entropia que permitia o fingerprinting.
O patch está no Bug 2024220 da Mozilla. As versões corrigidas:
| Produto | Versão Corrigida | Data |
|---|---|---|
| Firefox | 150 | 21/04/2026 |
| Firefox ESR | 140.10.0 | 21/04/2026 |
| Thunderbird | 150 | 21/04/2026 |
| Thunderbird | 140.10 | 21/04/2026 |
Os advisories relacionados: MFSA2026-30, MFSA2026-32, MFSA2026-33 e MFSA2026-34.
A simplicidade do fix levanta outra questão incômoda: se a solução era tão trivial, por que ninguém percebeu antes? O IndexedDB existe há mais de uma década. A API databases() não é nova. Quantos anos esse identificador ficou disponível para quem soubesse onde procurar?
Isso Não É a Primeira Vez
A Fingerprint.com já tinha encontrado problemas similares antes. Em 2022, eles descobriram que a implementação do IndexedDB no Safari 15 violava a same-origin policy, vazando nomes de bancos de dados entre origens. Antes disso, publicaram pesquisa sobre rastreamento cross-browser via protocol flooding afetando Chrome, Firefox, Safari e Tor.
Esse novo bug do Firefox é diferente dos anteriores — não viola a same-origin policy no sentido tradicional. Ele vaza um estado interno do processo através da ordenação dos resultados de uma API. É mais sutil, mais difícil de detectar, e por isso provavelmente ficou escondido por mais tempo.
O padrão que emerge é preocupante: APIs aparentemente inofensivas podem vazar informação de estado interno do navegador de formas que os desenvolvedores nunca anteciparam. Cada detalhe de implementação — a estrutura de dados escolhida, o algoritmo de hash, a decisão de não ordenar um resultado — pode se tornar um vetor de fingerprinting.
O Elefante na Sala: JavaScript É o Problema?
Uma reação natural a essa vulnerabilidade é: “bom, basta desabilitar JavaScript no Tor Browser.” E de fato, o nível de segurança “Safest” do Tor faz exatamente isso.
Mas aqui entra um paradoxo fascinante que um comentarista do HN (ranger_danger) apontou: desabilitar JavaScript na verdade aumenta sua visibilidade. Tão poucos usuários navegam sem JavaScript que você acaba em um conjunto de anonimato (anonymity set) minúsculo. É como tentar se esconder em uma multidão usando uma fantasia de dinossauro — tecnicamente você está coberto, mas todo mundo sabe que é você.
O Tor Project recomenda manter as configurações padrão exatamente por isso: quanto mais parecido você for com todos os outros usuários do Tor, mais difícil é te identificar.
Existe um debate antigo na comunidade de segurança sobre onde colocar a linha entre “API funcionando como esperado” e “API sendo explorada”. Um comentarista do HN (fc417fc802) levantou exatamente isso: se a informação está livremente disponível via uma API pública, isso é realmente uma vulnerabilidade? A resposta de outro usuário (strbean) foi direta: a Mozilla declarou explicitamente sua intenção de combater rastreamento. Qualquer mecanismo que permite tracking contra a vontade declarada do browser é, sim, uma vulnerabilidade — independente de como os dados são expostos tecnicamente.
A Superfície de Ataque Que Ninguém Mapeia
Esse caso ilumina um problema estrutural mais amplo. Os navegadores modernos expõem centenas de APIs JavaScript — Web Audio, WebGL, Canvas, Sensors, Bluetooth, WebRTC, e dezenas de outras. Cada uma delas tem detalhes de implementação que podem, potencialmente, vazar informações sobre o estado interno do processo.
Pesquisadores já demonstraram fingerprinting via:
- Canvas: renderização de texto e formas geométricas varia entre GPUs e drivers
- WebGL: parâmetros do renderizador expõem modelo exato da placa de vídeo
- AudioContext: processamento de áudio gera assinaturas únicas por hardware
- Fontes instaladas: a lista de fontes do sistema é surpreendentemente única
- Performance.now(): a precisão do timer pode revelar arquitetura do processador
O IndexedDB era considerado “seguro” nesse sentido. Ninguém esperava que a ordem de enumeração de uma API de armazenamento pudesse servir como canal lateral. E é exatamente aí que mora o perigo: nas APIs que ninguém está olhando.
Tom Ritter, líder técnico de anti-fingerprinting do Firefox, participou da discussão no Hacker News e fez uma distinção importante: existe diferença entre APIs que expõem comportamento intencional (como Canvas renderizando fontes) e side-channels não intencionais (como a ordem de iteração de hash tables). Ambos são problemas, mas o segundo tipo é sistematicamente mais difícil de prevenir porque ninguém projeta essas APIs pensando em vazamento de informação.
O Que Você Deve Fazer Agora
Se você usa Firefox, Tor Browser ou Thunderbird:
Atualize imediatamente. Não amanhã, não na próxima semana. Agora.
- Firefox → versão 150 ou superior
- Firefox ESR → versão 140.10.0 ou superior
- Thunderbird → versão 150 ou 140.10 ou superior
- Tor Browser → verifique se está usando a build mais recente (baseada no ESR corrigido)
Se você é desenvolvedor de navegadores ou extensões, esse bug é um lembrete valioso: nunca exponha a ordem de iteração de estruturas de dados internas. Hash tables, hash sets, hash maps — todos têm ordenação não-determinística por design. Se sua API retorna uma lista, ordene-a. Sempre.
E se você é alguém que depende do Tor para segurança real — ativista, jornalista, pesquisador em regime autoritário — considere adicionar o hábito de fechar completamente o navegador ao invés de apenas usar “Nova Identidade”. Pelo menos até que auditorias mais profundas confirmem que não existem outros identificadores de processo escondidos por aí.
O Verdadeiro Bug Não Era Técnico
No fim, o CVE-2026-6770 não é apenas um bug de privacidade. É um bug de confiança.
Quando o Tor Browser diz “Nova Identidade”, o contrato implícito é: “agora você é outra pessoa.” Milhões de pessoas em situações de risco real confiam nessa promessa. E durante um tempo indeterminado, essa promessa foi quebrada por uma hash table que ninguém pensou em ordenar.
A correção foi aplicada. O Firefox 150 já está disponível. Mas o episódio deveria incomodar qualquer pessoa que trabalha com segurança de software. Porque se uma API trivial como indexedDB.databases() escondeu um canal lateral por anos, o que mais está escondido em plain sight nas milhares de APIs que nossos navegadores expõem?
Às vezes, o bug mais perigoso não é o mais complexo. É o mais óbvio — aquele que ninguém pensou em procurar.
Fonte de inspiração: We Found a Stable Firefox Identifier Linking All Your Private Tor Identities — Fingerprint.com













