Contornar um filtro ingênuo
Uma lista de proibição que só apaga `<script>` deixa passar dezenas de outros vetores.
A primeira defesa que muita gente tenta é uma lista de proibição (blocklist): apagar o que parece perigoso. O caso clássico é remover a etiqueta <script>. O problema é que executar JavaScript não precisa de <script>: há muitos outros vetores.
<img src=x onerror=alert(1)>: a imagem falha, oonerrorroda.<svg onload=alert(1)>: dispara ao a página montar o elemento.<body onpageshow=...>,<details ontoggle=...>, e muitos mais.
Além disso, o próprio apagar pode ser contornado. Se o filtro remove <script> uma vez só, <scr<script>ipt> vira <script> depois da remoção. Se ele remove a palavra onerror, então ononerrorerror vira onerror quando o miolo é apagado.
A lição: filtrar por lista de proibição é uma corrida perdida, porque o atacante só precisa de um vetor que você esqueceu. A defesa certa não é adivinhar o que é perigoso, e sim codificar a saída (tratar tudo como texto) ou usar uma lista de permissão rígida de tags e atributos.