Pular para o conteúdo
Development

O bug atrás do bug

Por Victor Da Luz
securitymaintenancedev-logsite

Alguém apontou que a seção “On GitHub” deste site estava mostrando ícones de imagem quebrada em vez das minhas estatísticas e repositórios fixados. Bug simples, pensei, provavelmente coisa de CSP, já que eu tinha acabado de travar os cabeçalhos de segurança algumas issues atrás. Não era. Mas corrigir isso trouxe à tona um segundo bug, pior, que não tinha nada a ver com o GitHub.

O bug relatado: uma demo morta, não uma config morta. O card de estatísticas e os quatro cards de repositórios fixados carregam de github-readme-stats.vercel.app, uma ferramenta pública gratuita que muitos perfis do GitHub usam. Chamar direto com curl retornou 503 DEPLOYMENT_PAUSED, não um limite de taxa, não uma instabilidade passageira. Uma busca rápida trouxe uma sequência de issues abertas no repositório upstream desde janeiro: o mantenedor pausou o deploy público da demo, e continua pausado. O próprio README do projeto já diz isso, o endpoint público é “best-effort”, e a correção recomendada é hospedar você mesmo ou gerar as estatísticas via GitHub Actions.

Nenhuma das duas se encaixava bem aqui. Actions precisa de um nível de cobrança para repositórios privados do qual eu deliberadamente abri mão, e hospedar por conta própria significa um segundo serviço para manter por causa de um widget decorativo. Procurei uma alternativa genuína, algo que não trocasse um único ponto de falha por um idêntico, e não encontrei. Toda opção é ou “a demo gratuita de outra pessoa” ou “traga seu próprio token”. Acabei fazendo a coisa pragmática: trocando o domínio para um fork ativamente mantido, github-stats-extended.vercel.app, que é um substituto direto para a mesma API exata. Não é uma correção permanente. É o mesmo risco com um mantenedor mais saudável por trás, e escrevi isso claramente em vez de fingir o contrário.

O bug que eu não estava procurando. Enquanto verificava a correção num navegador de verdade, checei o console por violações de CSP por hábito, e encontrei uma que não tinha nada a ver com o GitHub. Um tempo atrás, eu tinha adicionado uma única linha ao script de lançamento do jogo para acessibilidade via teclado: mover o foco para o iframe do jogo depois do clique no botão. Razoável, pequeno, sem relação óbvia com segurança.

Só que o CSP deste site fixa exatamente esse script inline pelo hash SHA-256, um jeito legítimo de permitir um script inline específico sem abrir a porta para execução inline arbitrária. Mude um caractere no script, e o hash muda. Ninguém tinha recalculado. O build passou, a checagem de tipos passou, a formatação passou, nenhuma dessas sabe ou se importa com o que é um hash de CSP. O botão continuava com aparência normal. Clique nele, porém, e nada acontecia, silenciosamente, em produção, desde o deploy anterior.

Essa foi a parte que ficou comigo. Um CSP fixado por hash é mais seguro que 'unsafe-inline', e eu defenderia isso de novo. Mas também é uma armadilha sem alarme: não existe linter, teste, ou etapa de build que amarre o conteúdo de um script ao CSP que deveria permiti-lo. A única razão pela qual peguei isso foi hábito, rodar um navegador de verdade contra um build de verdade antes de considerar algo pronto, em vez de confiar no fato de que nada tinha dado erro.

Corrigi os dois na mesma passada, recalculei o hash, reverifiquei com a mesma checagem via navegador headless. Documentei o modo de falha direito dessa vez, com o comando real para recalcular o hash, para que da próxima vez que um ajuste de a11y de uma linha tocar nesse script, tenha algo para lembrar em vez de depender de pegar por acidente de novo.

Leitura relacionada

Development

Três vezes em que "a spec dizia X" estava errada

Um symlink apontando para lugar nenhum, uma correção já enfileirada pela automação, e docs descrevendo componentes que não existem, três fontes de verdade, a mesma lição em cada uma.

Ler
Development

Fechando a porta que ninguém usava

O domínio apex não enviava nenhum e-mail e não tinha registro SPF nem DMARC, o que significava que qualquer um podia forjá-lo. Dois registros DNS, noventa segundos num painel, um dig para verificar.

Ler
Development

O CSP que só quebrou em produção

Quatro falhas atrás de um único header: middleware morto, regras de _headers que se combinam em vez de sobrescrever, um worker de blob URL sob script-src, e um script que só o edge injeta.

Ler

Você também pode achar útil

Proton

Proton Pass

Gerenciador de senhas focado em privacidade, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
Proton

Proton VPN

VPN comercial com filtragem NetShield e interruptor de desligamento automático.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
Airalo

eSIM Airalo

eSIM de dados local para viagens - sem necessidade de trocar um SIM físico.

Este é meu link de indicação da Airalo. Você recebe um desconto no seu primeiro eSIM e eu ganho crédito da Airalo para o meu.

Saiba mais