Como funciona esta verificação
O Scanaris percorre o HTML da tua página principal e repara em dois tipos de etiqueta: <script src="..."> e <link rel="stylesheet" href="...">. Resolve cada URL contra o da página e considera-o externo se a sua origem (esquema, domínio e porta) for diferente da tua; isso inclui os URL que começam por //, que carregam da CDN com o protocolo da página. Descarta data: e blob:. Para cada recurso externo vê se tem o atributo integrity; se faltar, anota-o. Se houver pelo menos um, abre um achado de severidade baixa com o número de recursos e os primeiros dez URL. Os scripts e estilos do teu próprio domínio não são marcados: aí o SRI não acrescenta nada.
Porque importa
Quando carregas uma biblioteca de uma CDN estás a executar no browser dos teus utilizadores o que essa CDN decidir servir. Se a CDN for comprometida, ou se o domínio mudar de mãos, o ficheiro pode ser substituído por outro que faça o mesmo e ainda roube formulários ou redirecione para burlas. Aconteceu em junho de 2024 com o polyfill.io: o domínio foi vendido, o script começou a injetar código malicioso e mais de cem mil sites que o incluíam serviram-no sem dar conta. O atributo integrity contém o hash do ficheiro que tu reviste; o browser calcula o hash do que descarrega e, se não coincidir, não o executa. É severidade baixa porque exige que a CDN seja atacada primeiro, mas quando acontece, o dano é total e silencioso.
Como corrigir
Opção 1: adicionar integrity às etiquetas
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"
integrity="sha384-..." crossorigin="anonymous"></script>
O hash obtém-se descarregando o ficheiro exato e executando:
curl -s https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js | openssl dgst -sha384 -binary | openssl base64 -A
O cdnjs e o jsDelivr mostram o hash pronto a copiar junto a cada ficheiro. O atributo crossorigin="anonymous" é obrigatório para que o browser possa verificar um recurso de outra origem. E o URL deve apontar para uma versão fixa (@4.4.0), nunca para latest: se a CDN atualizar o ficheiro, o hash deixa de coincidir e o teu site deixa de carregar essa biblioteca, que é exatamente o que queres que aconteça perante uma mudança não revista.
Opção 2: servir as bibliotecas a partir do teu domínio
Instala-as com npm e deixa o teu bundler (Vite, webpack, Nuxt, Next.js) incluí-las no teu build. Assim o ficheiro sai do teu servidor, com hash no nome, e o SRI deixa de ser necessário. É a opção habitual em projetos modernos e a que resolve o achado pela raiz.
O que não admite SRI
As folhas de estilo do Google Fonts mudam conforme o browser que as pede, por isso o seu hash não é estável: ou aceitas esse achado ou alojas as fontes tu mesmo (o que ainda melhora a privacidade e a velocidade). Os scripts de analítica e de anúncios que se atualizam sozinhos (gtag.js, o pixel da Meta) também não admitem um hash fixo; aí a defesa é a CSP, que limita o que cada origem pode fazer e que mede CSP fraca.
Confirma que está corrigido
curl -s https://teudominio.com | grep -oE '<(script|link)[^>]*(src|href)="(https?:)?//[^"]+"[^>]*>' | grep -v integrity
Cada linha que sair é um recurso externo sem integrity. Se só ficarem os que não o admitem (fontes, analítica), terminaste.
Perguntas frequentes
O SRI atrasa o carregamento?
Não de forma apreciável: calcular um hash SHA-384 de um ficheiro de umas centenas de kilobytes leva milissegundos. O que faz é obrigar-te a fixar versões, o que é boa prática de qualquer forma.
Se atualizar a biblioteca, tenho de mudar o hash?
Sim, e é essa a graça: a atualização passa pelas tuas mãos. Se usas npm e o teu bundler, o processo é o mesmo de sempre e o hash é gerido pelo build.
E as versões velhas das bibliotecas da CDN?
O SRI garante que o ficheiro é o que tu escolheste, não que seja seguro. Um jQuery 1.12 com o hash correto continua a ter as suas falhas; isso deteta-o bibliotecas desatualizadas.