21 de nov. de 2025·8 min de leitura

CSRF e XSS em apps web gerados por IA: corrija padrões rapidamente

CSRF e XSS em apps web gerados por IA são comuns quando o código da UI é gerado automaticamente. Aprenda padrões vulneráveis e um checklist para fechar buracos sem reescrever telas.

CSRF e XSS em apps web gerados por IA: corrija padrões rapidamente

Por que CSRF e XSS aparecem em apps gerados por IA

CSRF e XSS aparecem com frequência em apps web gerados por IA por um motivo simples: muitos protótipos são feitos para parecerem corretos e funcionarem bem em demos, não para aguentar tráfego real. Uma página de login que “funciona localmente” ainda pode ser insegura quando é implantada, compartilhada e usada por pessoas que não são você.

O que “funciona localmente” esconde é a lacuna entre um ambiente de desenvolvimento privado e um app ao vivo. Localmente, raramente você lida com cookies reais entre múltiplas abas, conteúdo de terceiros, texto gerado por usuários em escala ou extensões de navegador que alteram o comportamento das páginas. Em produção, essas coisas aparecem rápido, e um ponto inseguro pode virar uma porta de entrada para muitas páginas.

Protótipos gerados por IA também tendem a pular o básico de segurança porque os prompts focam em funcionalidades. O modelo frequentemente escolhe o caminho mais curto: renderizar conteúdo do usuário diretamente, armazenar tokens em lugares inseguros ou enviar requisições que mudam estado sem proteção forte. Parece OK numa demo, mas deixa lacunas como tokens CSRF faltando ou HTML sendo injetado na página.

Padrões pequenos podem ter grande raio de ação. Um componente que usa dangerouslySetInnerHTML para renderizar “notas formatadas” pode transformar a entrada de um usuário em um script que roda para todo visualizador. Um botão “Excluir” que chama uma API sem checagem CSRF pode permitir que um atacante dispare ações usando a sessão autenticada da vítima.

“Sem reescrever a UI” é realista, com limites. Normalmente você não precisa redesenhar telas nem reconstruir componentes do zero. Adiciona-se proteção por baixo: padrões de renderização mais seguros, wrappers de requisição consistentes e checagens no servidor que rejeitam requisições inseguras. A UI pode ficar idêntica enquanto o app fica bem mais difícil de ser abusado.

Se você herdou uma base de código gerada por IA e está vendo esses padrões, um passo prático inicial é uma auditoria rápida para encontrar os poucos buracos de alto impacto que tornam todo o resto arriscado, e então corrigi-los sem mudar a aparência. A FixMyMess normalmente começa exatamente aí: diagnóstico do código primeiro, depois reparos direcionados.

CSRF vs XSS em linguagem simples

CSRF e XSS se misturam porque ambos podem levar a “alguém fez algo no meu app que eu não esperava”. A diferença é onde o controle do atacante acontece.

CSRF (Cross-Site Request Forgery) em uma frase: engana o navegador de um usuário logado para enviar uma requisição real que seu servidor aceita.

XSS (Cross-Site Scripting) em uma frase: permite que código controlado pelo atacante rode dentro do seu site no navegador do usuário.

Uma forma rápida de lembrar: CSRF abusa do login do seu usuário (normalmente cookies). XSS abusa da sua página.

Como eles se encadeiam

Sozinhos são ruins, juntos são piores. Uma cadeia comum é:

  1. Um bug de XSS roda no seu app e lê algo sensível (como um token CSRF na página ou um JWT no localStorage).
  2. O atacante usa esse segredo para enviar requisições autenticadas que parecem legítimas.
  3. Essas requisições executam ações (trocar e-mail, adicionar um admin, transferir créditos) sem o usuário perceber.

Por isso “vamos adicionar CSRF depois” frequentemente falha se já existe um buraco de XSS.

Sinais simples de que você pode ter cada problema

Se você usa autenticação baseada em cookies, o risco de CSRF é provável quando ações importantes funcionam com um único POST e sem token por requisição, ou quando sua API aceita requisições sem checar o cabeçalho Origin ou Referer. O risco também aumenta com sessões de longa duração (“lembrar-me”) e apps que confiam em “é um dashboard privado” como proteção.

Risco de XSS é provável quando você renderiza conteúdo do usuário com dangerouslySetInnerHTML (ou similar), insere HTML cru vindo de um editor rich text ou Markdown sem sanitizar, constrói strings HTML e as define via innerHTML, ou ecoa entrada do usuário de volta na página (comentários, nomes, termos de busca).

Se você herdou um protótipo gerado por IA, essas duas questões aparecem muito em builds rápidos. O caminho mais rápido é confirmar qual risco é real no seu app e então corrigi-lo sem alterar o layout da UI.

Padrões vulneráveis de XSS para procurar primeiro

XSS geralmente entra quando uma UI gerada por IA toma um atalho para “parecer certo” e acaba tratando texto como HTML. Comece encontrando todo lugar onde o app transforma conteúdo controlado pelo usuário em marcação.

Os alertas mais rápidos

Código gerado costuma incluir alguns atalhos de alto impacto:

  • dangerouslySetInnerHTML usado para formatação rápida, destaque ou inserção de snippets ricos.
  • Conteúdo do usuário renderizado como HTML (comentários, biografias, tickets de suporte, pré-visualizações de Markdown).
  • HTML construído por concatenação de strings (template strings que contêm \\u003cdiv\\u003e / \\u003ca\\u003e / \\u003cimg\\u003e).
  • Dados não confiáveis colocados em atributos (especialmente href, src, style ou data-*) ou manipuladores de evento inline como onclick="...".
  • Helpers de “sanitização” copiados e colados que só removem algumas tags, usam regex, ou apenas escapam \\u003c e \\u003e.

Uma falha realista: um dashboard mostra um campo “Release notes” puxado do banco. Alguém cola \\u003cimg src=x onerror=alert(1)\\u003e e de repente todo admin que abre a página executa esse código. Também pode roubar tokens de sessão, mudar texto da UI ou submeter ações silenciosamente.

O que procurar no código

Use buscas simples primeiro. O objetivo é criar um inventário, não consertar ainda.

- dangerouslySetInnerHTML
- innerHTML =
- insertAdjacentHTML
- onClick="  onerror="  onload="
- href={user
- `\\u003cdiv`  `\\u003c/` (inside template strings)

Se você herdou um protótipo de ferramentas como v0, Replit ou Cursor, esses atalhos aparecem bastante. Trate qualquer função de sanitização caseira como suspeita até provar que é segura. A FixMyMess frequentemente vê “sanitizadores” que deixam passar payloads em SVG, atributos de evento ou URLs javascript:.

Padrões vulneráveis de CSRF para procurar primeiro

CSRF aparece quando seu app confia demais em um cookie do navegador. Muitos protótipos gerados por IA “funcionam” em dev porque você está sempre logado, mas o mesmo design vira risco em produção.

Comece caçando qualquer requisição que mude dados mas não prove que o usuário pretendia fazê-lo. O jeito mais rápido é olhar rotas do servidor e chamadas de API do frontend lado a lado.

Padrões de alto risco para checar hoje

Padrões comuns de alto risco incluem:

  • Requisições POST/PUT/DELETE que dependem de um cookie de sessão mas não enviam um token CSRF (ou não o validam no servidor).
  • Cookies de autenticação sem política SameSite clara (ou SameSite=None sem motivo forte).
  • Endpoints GET que mudam estado (por exemplo: /api/deleteUser?id=123 ou /api/toggle?id=...).
  • Pensar “Habilitamos CORS, então estamos seguros”. CORS controla quais sites podem ler respostas, não quais sites podem enviar requisições.
  • Múltiplos subdomínios que compartilham cookies de forma confusa, especialmente quando o Domain do cookie é amplo demais.

Um exemplo rápido: um dashboard de protótipo tem um botão que chama GET /api/approveInvoice?id=42. Se um atacante consegue fazer um admin carregar uma página que dispara essa URL, o navegador pode enviar automaticamente o cookie do admin.

Armadilhas com cookies e subdomínios

Se seu app usa app.example.com e api.example.com, seja explícito sobre o escopo dos cookies e o que está autorizado a enviar requisições autenticadas. Domínios de cookie amplos junto com checagens CSRF ausentes é uma armadilha comum de “funcionou localmente”.

Se quiser uma auditoria rápida, a FixMyMess pode sinalizar esses padrões de CSRF rapidamente (incluindo problemas de escopo de cookie) antes de você tocar na UI.

Corrigir CSRF sem mudar o layout da UI

Rescue an Inherited Codebase
Inherited a messy prototype? We can stabilize it quickly, with expert human verification.

A maioria das correções de CSRF vive em cookies, cabeçalhos e middleware no servidor. Por isso você normalmente pode travar CSRF sem redesenhar uma única página.

Escolha uma estratégia de CSRF

Duas abordagens comuns funcionam bem com frontends gerados por IA:

  • Token sincronizador: o servidor cria um token, guarda na sessão e exige esse token em cada requisição que muda estado.
  • Double-submit cookie: o servidor seta um cookie CSRF e exige o mesmo valor em um cabeçalho (ou no corpo) da requisição. Não precisa de sessão no servidor.

Se seu app já usa cookies para autenticação, double-submit cookie mais um cabeçalho costuma ser o menos disruptivo. A UI fica igual. Você só adiciona um cabeçalho no cliente.

Checagens no backend que não tocam a UI

Coloque a aplicação de CSRF na entrada do backend: middleware, classe base do controller ou um guard único de requisições. Aplique para métodos inseguros (POST, PUT, PATCH, DELETE) e só para tráfego autenticado por cookie do navegador.

Um padrão prático é:

  • Setar um cookie CSRF no carregamento inicial da página ou depois do login.
  • Exigir X-CSRF-Token nas requisições inseguras.
  • Comparar o token do cabeçalho com o token do cookie (rejeitar se faltar ou não bater).
  • Pular checagens CSRF para endpoints que usam Authorization headers (API keys, bearer tokens) em vez de cookies.
  • Logar rejeições com rota e origem para você pegar quebras acidentais rápido.

Confirme as configurações de cookie enquanto estiver nisso. Use SameSite=Lax por padrão, Secure em produção (HTTPS) e HttpOnly para cookies de autenticação. Para cookies CSRF especificamente, você pode precisar de HttpOnly=false se o browser precisar ler o cookie para copiar num cabeçalho.

Se tiver APIs usadas tanto por código do navegador quanto por código do servidor (SSR, cron jobs, webhooks), separe-as: rotas baseadas em cookie recebem checagem CSRF; rotas baseadas em token não. Times frequentemente pedem à FixMyMess para adicionar essa separação quando um protótipo gerado por IA começa a falhar em produção.

Corrigir XSS sem mudar o layout da UI

Correções de XSS não precisam significar redesenho. Na maioria das vezes você pode manter os mesmos componentes e rotas e só mudar como texto e HTML são renderizados. Isto é comum em apps gerados por IA: a UI parece OK, mas os padrões de renderização são inseguros.

Torne “apenas texto” o default

Trate toda string como não confiável, mesmo que venha do seu próprio banco. Comentários, nomes de perfil, “notas”, mensagens de suporte e qualquer coisa produzida por um LLM podem carregar HTML escondido.

Foque em alguns padrões que fecham a maior parte dos buracos:

  • Remova ou limite estritamente dangerouslySetInnerHTML (e APIs similares em outros frameworks).
  • Renderize conteúdo do usuário como texto puro por padrão (sem interpretação de HTML).
  • Se precisar permitir rich text, sanitize com uma biblioteca conhecida e uma allowlist pequena.
  • Coloque o encoding de saída em um único lugar (um helper/componente) para que os consertos se apliquem em todo lugar.
  • Trate Markdown também como não confiável (Markdown pode gerar HTML dependendo do parser).

Se realmente precisar de HTML (por exemplo, um editor de “release notes”), sanitize imediatamente antes de renderizar e permita apenas um conjunto pequeno de tags (como b, i, em, strong, a). Evite manipuladores de evento inline, estilos inline e atributos desconhecidos.

// Example pattern (React): sanitize before using dangerouslySetInnerHTML
const safeHtml = sanitize(userProvidedHtml, { allowTags: ['b','i','em','strong','a'] });
return \u003cdiv dangerouslySetInnerHTML={{ __html: safeHtml }} /\u003e;

Adicione um CSP como rede de segurança

Uma Content Security Policy (CSP) não corrige renderização ruim, mas pode limitar o dano se algo escapar.

Comece simples, então teste seu app e afrouxe só o que for necessário:

  • Bloqueie scripts inline quando possível.
  • Permita scripts apenas do seu próprio domínio.
  • Proíba URLs javascript: em links.
  • Evite unsafe-eval a menos que não haja escolha.

Se você herdou um protótipo gerado por IA e não tem certeza de onde o HTML inseguro está vindo, um bom fluxo de trabalho é encontrar cada caminho de renderização arriscado, substituí-lo por padrões seguros e então adicionar CSP para capturar os restos.

Hardening passo a passo em menos de um dia

Você pode fechar a maior parte dos buracos de CSRF e XSS sem tocar no layout. O truque é trabalhar como um testador primeiro, depois corrigir a menor superfície possível.

Comece mapeando como os dados se movem. Faça um inventário rápido de onde os dados entram (forms, query params, cookies, webhooks, campos rich text) e onde são mostrados de volta a um usuário (tabelas, toasts, páginas de perfil, painéis admin). Isso frequentemente revela caminhos “escondidos” como uma página de configurações internas que nunca foi revisada.

Em seguida, torne suas correções visíveis. Ligue logs no servidor para falhas de CSRF (tokens rejeitados, checagens de origem faltando). Para XSS, adicione um sinal claro quando a sanitização remover conteúdo. Se um usuário reportar “meu texto sumiu”, você quer ver o que foi removido e por quê.

Um plano de correção rápido

  • Adicione proteção CSRF a todas as rotas que mudam estado (POST, PUT, PATCH, DELETE) usando middleware compartilhado, e confirme que cookies têm defaults sensatos (HttpOnly, Secure, SameSite).
  • Padronize como o cliente envia o token (cabeçalho ou campo oculto) para não consertar de cinco maneiras diferentes.
  • Busque por dangerouslySetInnerHTML e padrões similares. Remova-os quando possível, ou isole-os em um componente único que sempre sanitize.
  • Sanitize HTML não confiável em um único limite (imediatamente antes da renderização, ou ao salvar). Escolha um, documente e mantenha consistente.
  • Adicione uma CSP básica e rode seus fluxos principais para pegar scripts inline acidentais cedo.

Depois, reteste como um usuário normal: registre-se, faça login, atualize um perfil, submeta um formulário e use ações de admin. Tente as mesmas ações num segundo navegador onde você não está logado. Se algo quebrar, os logs devem indicar se foi proteção CSRF ou sanitização.

Se você herdou uma base de código gerada por IA, a FixMyMess pode rodar uma auditoria rápida e aplicar esses patches com verificação humana experiente, assim você ganha segurança sem reescrever tudo.

Exemplo: dashboard de protótipo que quebra em produção

Harden Security Without Rework
We patch CSRF and XSS without redesigning your UI or slowing down your roadmap.

Uma configuração comum é um “admin dashboard” mais uma caixa de comentários pública. A UI parece OK: admins aprovam usuários, emitem reembolsos e alteram preços. Visitantes deixam feedback que aparece num feed no dashboard.

O XSS entra quando comentários são renderizados como HTML. Um padrão típico é um componente React que usa dangerouslySetInnerHTML para que quebras de linha e links “simplesmente funcionem”. Se um visitante digita algo que vira código script, pode executar na sessão do admin quando ele abre o dashboard.

CSRF entra quando ações de admin dependem apenas de cookies para autenticação. Os botões chamam endpoints como /api/admin/refund, e o servidor assume “cookie presente” como “admin aprovou essa ação”. Se um admin estiver logado e visitar uma página maliciosa em outra aba, essa página pode submeter um formulário ou requisição oculta ao seu app, e o navegador anexará o cookie do admin.

Um caminho de ataque realista: o atacante posta um “comentário” que roda na sessão do admin, então dispara requisições que mudam estado contra endpoints sem CSRF. Não é mágica — é o navegador fazendo o que sempre faz.

Correções mínimas que mantêm as mesmas telas e UX:

  • Pare de renderizar HTML cru dos comentários. Renderize texto por padrão, ou sanitize e permita só um conjunto pequeno e seguro (negrito, itálico, links).
  • Adicione proteção CSRF a todas as requisições que mudam estado e exija isso em POST/PUT/PATCH/DELETE.
  • Defina cookies de sessão para SameSite=Lax (ou Strict quando possível) e HttpOnly.
  • Exija checagens de Origin ou Referer para ações admin sensíveis como backup.

Times frequentemente trazem esse dashboard exato para a FixMyMess quando “funciona localmente” mas falha numa revisão de segurança real. A boa notícia é que geralmente dá para corrigir sem mudar a UI.

Erros comuns e falsos consertos

Muitos consertos rápidos parecem “seguros” porque silenciaram um alerta ou bloquearam um exploit óbvio. O problema real costuma ser que o mesmo padrão inseguro existe em dois ou três lugares que você não pensou em checar.

Uma armadilha comum é escapar input uma vez (talvez no handler do form) e depois renderizar os mesmos dados por um caminho diferente que pula esse escape. Exemplo: um campo “notas” é escapado ao salvar, mas um painel de pré-visualização usa dangerouslySetInnerHTML para formatação e traz a execução de script de volta.

Outro falso conserto é sanitizar só no navegador e confiar no resultado no servidor. Atacantes não usam sua UI. Eles enviam requisições diretamente, então o servidor deve validar e o app deve codificar a saída não importa o que o cliente faz.

Pessoas também assumem que JSON é “seguro”. Não é. Se você pega campos JSON e injeta no HTML (templates, tooltips, toasts, componentes rich text), ainda pode ter XSS. O formato da resposta não é proteção; o que importa é como você a renderiza.

Widgets de terceiros frequentemente são esquecidos. Widgets de chat, snippets de analytics, editores Markdown e componentes embed podem injetar HTML ou scripts. Mesmo que seu código esteja limpo, uma configuração insegura de um widget pode desfazer seu trabalho.

Para CSRF, um erro frequente é proteger um endpoint e deixar outro que muda estado aberto. A UI pode chamar /settings/update, mas existe também /settings/save ou /api/admin/promote que ainda aceita cookies sem checagem CSRF.

Verificações rápidas de realidade que pegam a maioria dos apps “consertados mas ainda vulneráveis”:

  • Busque por todo caminho de renderização do conteúdo do usuário, não só o formulário que o coleta.
  • Faça validação no servidor e encoding de saída, mesmo se o cliente sanitiza.
  • Revise rotas que mudam estado (POST, PUT, PATCH, DELETE) e confirme que todas exigem proteção CSRF.
  • Inventarie scripts e componentes de terceiros e reveja como eles injetam conteúdo.

Times frequentemente trazem à FixMyMess um protótipo que “funciona” em demos mas falha nessas checagens em produção. As vitórias mais rápidas normalmente vêm de fechar caminhos extras de renderização e endpoints esquecidos, não de reescrever a UI.

Checklist rápido antes de enviar para produção

Close Common Security Gaps
Add CSRF protection, safer rendering defaults, and security checks that hold up under traffic.

Antes de enviar um protótipo gerado por IA para usuários reais, faça uma passada focada em dois escapes comuns: mudanças de estado sem proteção CSRF e conteúdo não confiável que pode virar script.

  • Proteja todas as rotas que mudam estado (POST/PUT/PATCH/DELETE). Exija um token CSRF (ou defesa equivalente) e rejeite requisições que não o tenham.
  • Trave cookies: defina Secure e HttpOnly quando possível, e escolha um valor SameSite que combine com seus fluxos (cuidado com redirecionamentos de terceiros e apps embutidos).
  • Não renderize HTML não confiável a menos que passe por um sanitizador com allowlist. Se não precisa de HTML, renderize texto puro.
  • Adicione uma CSP e teste suas páginas principais com ela ativada. Uma política que bloqueia scripts inline pega muitos caminhos acidentais de XSS.
  • Reteste login, signup, reset de senha e logout depois das mudanças. Correções de segurança costumam quebrar auth de formas pequenas (tokens não enviados, cookies não setados, redirects em loop).

Então rode um pequeno conjunto de testes pré-deploy:

  • Tente o app em uma janela privada e confirme que cookies se comportam como esperado após o login.
  • Envie uma requisição que mude estado sem token CSRF e confirme que falha.
  • Cole uma prova inofensiva de XSS (como \\u003cimg src=x onerror=alert(1)\\u003e) em qualquer campo que depois apareça numa página; confirme que é renderizada como texto e não executa.
  • Abra páginas-chave com CSP ligada e confirme que nada essencial quebra (botões, modais, envio de formulários).

Se você herdou uma base de código gerada por IA e esses testes descobrem um monte de casos borda, a FixMyMess pode auditar e corrigir as partes arriscadas rapidamente sem forçar um rewrite de UI.

Próximos passos se você herdou um código gerado por IA

Comece decidindo se precisa de consertos rápidos ou de um sprint curto de limpeza. Se o app é pequeno, tem login simples e só alguns formulários, frequentemente dá para fechar os maiores gaps de CSRF e XSS sem tocar na UI. Se o código tem lógica de auth copiada e colada, muitas chamadas fetch duplicadas e renderização HTML espalhada, só consertar pode virar um jogo de whack-a-mole.

Consertos rápidos costumam bastar quando você tem um número pequeno de ações de escrita que passam por um único wrapper cliente, texto gerado por usuário exibido em alguns componentes óbvios, e sessões/cookies comportando-se de forma consistente no app.

Planeje limpeza quando ver calls fetch duplicadas, propriedade de cookies/tokens pouco clara ou endpoints admin “temporários” que foram lançados.

Para obter uma revisão rápida e útil, entregue ao revisor um mapa simples do que existe hoje. O objetivo é achar os hotspots onde esses problemas se escondem, não criticar sua UI.

Aqui está o que preparar (mesmo um doc raso serve):

  • Uma lista de cada endpoint que muda dados (método + caminho + quem pode chamá-lo)
  • Como a auth funciona (cookies vs headers, onde a sessão é criada, comportamento de logout)
  • Onde HTML é renderizado ou injetado (helpers de render, markdown, rich text, pré-visualizações de e-mail)
  • Quais embeds de terceiros ou inputs de conteúdo de usuário existem (comentários, campos de perfil, uploads)
  • Onde segredos vivem (arquivos env, bundle cliente, logs de CI)

Uma auditoria curta costuma identificar padrões arriscados rápido: checagens CSRF faltando em sessões baseadas em cookie, renderização HTML insegura e lugares onde dados não confiáveis chegam ao DOM.

Se o app já está quebrando em produção, considere um sprint de remediação direcionado: corrija as vulnerabilidades mais críticas, adicione guardrails (tokens, sanitização, defaults seguros) e então refatore só os piores culpados.

Se quiser uma visão externa, a FixMyMess (fixmymess.ai) se concentra em consertar bases de código geradas por IA de ferramentas como Lovable, Bolt, v0, Cursor e Replit, incluindo problemas como fluxos de auth quebrados, segredos expostos, CSRF/XSS e hardening de segurança, mantendo a UI intacta.