Aikido

As 10 Principais Vulnerabilidades de Segurança em JavaScript em Aplicações Web Modernas

Ruben CamerlynckRuben Camerlynck
|
#
#

As 10 Principais Vulnerabilidades de Segurança em JavaScript

JavaScript impulsiona uma vasta gama de aplicações modernas – desde front-ends web dinâmicos até back-ends Node.js escaláveis – o que significa que também expõe uma ampla superfície de ataque. A flexibilidade que torna o JavaScript tão poderoso pode se transformar em uma faca de dois gumes quando a segurança é negligenciada. O código de front-end é executado diretamente nos navegadores dos usuários (e pode ser inspecionado ou manipulado por atacantes), enquanto aplicações Node.js de back-end frequentemente integram inúmeros pacotes e lidam com dados sensíveis. A dura verdade é que uma única linha de JavaScript insegura ou uma dependência vulnerável pode abrir a porta para exploits. De fato, relatórios recentes da indústria mostram que aplicações web continuam repletas de vulnerabilidades comuns como cross-site scripting e bibliotecas desatualizadas, apesar de anos de avisos.

Cada script tag, cada npm install, e cada parse de JSON pode estar escondendo um risco potencial. Nas seções abaixo, detalhamos as dez principais vulnerabilidades de segurança JavaScript (abrangendo problemas tanto do lado do cliente quanto do lado do servidor), com exemplos do mundo real e dicas sobre como corrigi-las ou preveni-las. De armadilhas clássicas como XSS a ataques à Supply chain, cada vulnerabilidade inclui etapas de mitigação e um destaque sobre como as ferramentas de segurança modernas (como SAST do Aikido, detecção de Secrets, e análise de dependências) podem ajudar a identificar problemas precocemente.

1. Ataques de cross-site scripting (XSS)

Cross-Site Scripting (XSS) is one of the most prevalent vulnerabilities in we11b applications year after year. XSS occurs when an application includes unsanitized user input in a webpage, allowing attackers to inject malicious JavaScript that executes in the browsers of other users. This can lead to session hijacking, defacement, and theft of sensitive data. Even widely used libraries have suffered XSS flaws – for example, a five-year-old jQuery bug (CVE-2020-11023) allowed arbitrary code execution by passing malicious HTML to jQuery’s DOM methods. Unsuspecting developers who included a vulnerable jQuery (<3.5.0) version in their frontend exposed their users to potential XSS, a flaw so serious that U.S. CISA added it to its exploited vulnerabilities catalog in 2025.

Exemplo do mundo real: Um atacante pode criar um comentário ou nome de perfil contendo <script> tags em um fórum que não escapa a saída corretamente. Quando outros usuários visualizam essa página, o script é executado em seus navegadores – talvez roubando seu cookie de sessão ou se passando por eles. Relatório de segurança da Claranet de 2024 encontrado 2.570 instâncias de XSS (refletido e armazenado) em 500 testes de penetração, tornando-o “uma das vulnerabilidades mais comuns encontradas… nos últimos cinco anos”. Isso ressalta que o XSS continua sendo uma das principais ameaças em aplicações com uso intensivo de JavaScript.

Mitigação: A defesa contra XSS requer uma combinação de práticas de codificação e defesas do navegador:

  • Escape e Validação da Saída: Nunca injete entrada de usuário bruta em HTML. Sanitize a entrada na chegada e faça o escape da saída no contexto apropriado (HTML, atributo, JavaScript, etc.).
  • Use Controles de Framework: Aproveite frameworks de templating ou frontend (React, Angular, Vue) que automaticamente fazem o escape ou sanitizam o conteúdo. Evite usar sinks perigosos como innerHTML ou document.write com dados dinâmicos – use alternativas mais seguras como textContent.
  • Content Security Policy (CSP): Implemente um cabeçalho CSP rigoroso para restringir de onde os scripts podem ser carregados. O CSP pode atuar como uma segunda linha de defesa bloqueando scripts não autorizados.
  • Cookies HttpOnly e SameSite: Marque os cookies como HttpOnly (não acessíveis via JS) e use SameSite atributos para dificultar alguns tipos de ataques (como cross-site scripting roubando cookies ou CSRF).

Detectar XSS exige vigilância na revisão de código e testes. Os Testes de segurança de aplicações estáticas (SAST) do Aikido podem sinalizar padrões perigosos – por exemplo, o uso de innerHTML com dados fornecidos pelo usuário ou codificação de saída ausente em templates de servidor. A análise de dependências também ajuda: Aikido alertaria você se estivesse usando uma versão antiga de biblioteca conhecida por habilitar XSS (como o exemplo do jQuery 3.4.1 acima) para que você possa atualizar para uma versão corrigida. Ao integrar varreduras automatizadas em seu CI/CD, você pode detectar vulnerabilidades de XSS precocemente, antes que os atacantes o façam.

2. Prototype Pollution

Prototype pollution é uma vulnerabilidade específica do JavaScript que explora a natureza dinâmica dos protótipos de objetos. No JavaScript, objetos herdam propriedades de seu protótipo, e se um atacante puder injetar propriedades em Object.prototype, essas propriedades se tornam acessíveis em todos os objetos – frequentemente levando a negação de serviço ou até mesmo execução remota de código. Muitas bibliotecas populares sofreram CVEs de prototype pollution. Por exemplo, versões do Lodash anteriores a 4.17.12 tinham uma vulnerabilidade em suas defaultsDeep e outras funções que poderiam ser enganadas para modificar Object.prototype via a crafted payload. Another example is Handlebars.js: versions <4.3.0 allowed template input to alter special properties like __proto__, o que “pode permitir que um atacante execute código arbitrário” no servidor (CVE-2019-19919).

Exemplo do mundo real: Um atacante submete dados JSON a uma API com um payload como {"__proto__": {"admin": true}}. Se a aplicação mescla objetos sem proteção (por exemplo, usando um lodash.merge desatualizado ou similar), a cadeia de protótipos é poluída – subsequentemente, verificações como if(user.admin) podem retornar inesperadamente `true` para todos os usuários, ou pior, a lógica da aplicação pode ser subvertida. Em alguns casos, a poluição de protótipos pode ser combinada com outras técnicas para executar código. Por exemplo, a falha de “prototype poison” em templates Handlebars mencionada acima poderia ser usada para executar JavaScript server-side no contexto da aplicação.

Mitigação: Para prevenir a poluição de protótipos:

  • Atualizar Dependências: Use versões corrigidas de bibliotecas que tenham corrigido bugs de poluição de protótipos. Por exemplo, atualize o Lodash para >=4.17.20 (que corrigiu múltiplos CVEs desse tipo).
  • Validação de Entrada: Valide e sanitize entradas JSON ou de objetos. Rejeite ou filtre chaves de objeto nomeadas __proto__, constructor, ou protótipos nos dados.
  • Mesclagem Segura de Objetos: Ao mesclar objetos (por exemplo, clonagem profunda ou extensão), use funções ou bibliotecas seguras que não copiam propriedades de protótipo. Algumas bibliotecas de utilidade fornecem opções para ignorar propriedades herdadas.
  • Executar em Modo Estrito: Embora não seja uma solução mágica, o modo estrito ("use strict") pode prevenir certas ações perigosas e tornar os bugs mais fáceis de serem detectados.

A poluição de protótipo pode ser sutil, mas a análise de dependências é sua aliada aqui. O scanner de dependências do Aikido sinalizará versões vulneráveis conhecidas de bibliotecas como Lodash, jQuery ou Handlebars que são suscetíveis à poluição de protótipo, para que você possa atualizá-las proativamente. No lado do código, o motor SAST do Aikido pode detectar padrões de fusão insegura de objetos ou uso de chaves de objeto potencialmente perigosas. Ao usar o Aikido para auditar continuamente tanto seu código quanto seus pacotes npm, você obtém uma rede de segurança para essa classe de bug – detectando-o durante o desenvolvimento, em vez de após uma violação.

3. Desserialização Insegura

Falhas de desserialização insegura ocorrem quando uma aplicação aceita dados serializados não confiáveis e os desserializa em objetos sem validação adequada. Em JavaScript/Node, isso geralmente envolve funções que recebem objetos JSON ou JavaScript fornecidos pelo usuário e os “revivem” em objetos ativos. Se não for tratada com cuidado, a desserialização pode ser abusada para executar código arbitrário ou manipular o estado da aplicação. Um exemplo notório foi a node-serialize vulnerabilidade do pacote (CVE-2017-5941): ela permitia que atacantes passassem um objeto serializado malicioso contendo uma Immediately-Invoked Function Expression (IIFE). Após a desserialização, a função seria executada no servidor, efetivamente alcançando a execução remota de código.

Exemplos do mundo real: Este problema não é teórico – mesmo grandes frameworks cometeram erros. No final de 2025, uma vulnerabilidade crítica do React/Next.js (apelidada de React2Shell, CVE-2025-55182) foi divulgada, enraizada na forma como os React Server Components lidam com dados serializados. “No centro do problema está a desserialização insegura”, observou a pesquisa da Akamai, que permitiu aos atacantes injetar chaves de objeto maliciosas, levando à poluição de protótipo e, em última instância, à execução remota de código no servidor. Isso significa que, ao enviar uma requisição HTTP especialmente elaborada, um atacante não autenticado poderia assumir o controle de um servidor Node.js executando código React vulnerável – um cenário de pesadelo para qualquer equipe DevSecOps.

Mitigação: Prevenir a desserialização insegura envolve o manuseio cuidadoso dos formatos de dados:

  • Preferir Formatos Seguros: Use JSON para intercâmbio de dados e evite analisar código ou funções JavaScript de entrada do cliente. JSON.parse padrão é mais seguro do que eval() ou desserialização personalizada de objetos JS.
  • Whitelisting e Validação: Se você precisar aceitar objetos serializados, implemente esquemas rigorosos ou whitelists. Permita apenas propriedades e tipos de objetos esperados. Rejeite qualquer entrada contendo chaves como __proto__ ou constructor que possam ser vetores de abuso.
  • Evite eval e Function(): Não use eval() em JSON ou aceite código JS bruto de clientes. Da mesma forma, evite bibliotecas que executam dados de objetos (por exemplo, evite executar automaticamente funções que vêm de entrada analisada).
  • Atualizações de Biblioteca: Mantenha-se atualizado sobre os patches de framework. A vulnerabilidade do React mencionada acima foi corrigida por atualizações para React/Next – aplique esses patches imediatamente e monitore os avisos para bibliotecas Node.js que realizam desserialização.

A plataforma do Aikido pode ajudar a detectar desserialização insegura de algumas maneiras. Análise estática de código irá avisá-lo se seu código estiver usando funções arriscadas (como unserialize() de uma biblioteca desatualizada ou usando eval na entrada). Se você estiver usando pacotes conhecidos por serem vulneráveis (como o com bugs node-serialize <=0.0.4, or certain versions of React), Aikido’s dependency scanner would flag those by CVE. Additionally, Aikido’s runtime SAST analysis (if integrated in testing) can observe data flows – for example, user input flowing into a dangerous sink – and alert you. The bottom line: integrating such tools in CI means you’d catch something like React2Shell in your code antes ele se torna React2Shell nas notícias.

4. Cross-Site Request Forgery (CSRF)

Cross-Site Request Forgery (CSRF) é uma vulnerabilidade web clássica que frequentemente afeta aplicações baseadas em JavaScript (ou qualquer aplicação web com sessões). Ao contrário do XSS, que explora a injeção de código, o CSRF explora a confiança no navegador do usuário. Ele permite que um atacante engane o navegador da vítima para fazer requisições não intencionais à sua aplicação, sob o pretexto das próprias credenciais da vítima. Em termos mais simples, se um usuário estiver logado em seu site, um atacante pode potencialmente induzir seu navegador (através de um link ou imagem maliciosa) a realizar ações como alterar detalhes da conta ou iniciar transações sem o consentimento do usuário.

Exemplo do mundo real: Um exemplo bem conhecido é a analogia de post de fórum/transferência bancária – imagine um aplicativo bancário onde o formulário de transferência de dinheiro é vulnerável a CSRF. Um atacante poderia enviar a um usuário logado um link (ou incorporar um formulário de envio automático em uma página maliciosa) que aciona POST /transfer?amount=1000&to=attackerAccount. Se o aplicativo bancário não tiver proteção CSRF, o navegador do usuário enviará diligentemente essa requisição junto com os cookies de sessão, e o banco a executará pensando que o usuário a intencionou. No contexto do JavaScript, Single Page Applications (SPAs) podem depender de APIs que usam cookies para autenticação; se essas APIs não implementarem defesas CSRF (como exigir um token ou cookies same-site), elas são igualmente exploráveis. Mesmo frameworks que incluem tokens CSRF podem ser mal configurados – por exemplo, se o backend de um aplicativo Angular ou React definir uma política CORS excessivamente ampla ou flags SameSite ausentes, ataques CSRF podem passar despercebidos.

Mitigação: As principais estratégias para parar o CSRF incluem:

  • Tokens CSRF: Incorpore tokens imprevisíveis em formulários ou chamadas de API e verifique-os no lado do servidor. Frameworks modernos frequentemente possuem middleware CSRF. Garanta que os tokens estejam vinculados à sessão do usuário e sejam verificados em cada requisição que altera o estado.
  • SameSite Cookies: Defina os cookies de sessão com o SameSite=Lax ou Strict atributo. Isso restringe os navegadores de enviar cookies em requisições cross-site (o mecanismo primário de CSRF). Notavelmente, Strict pode quebrar alguns fluxos legítimos, então Lax é um padrão equilibrado para a maioria das aplicações.
  • Cabeçalhos Personalizados e Verificação de Origem: Para APIs (especialmente se usando fetch/XHR em SPAs), você pode exigir um cabeçalho personalizado (por exemplo, X-Requested-With: XMLHttpRequest) e rejeitar requisições que não o possuam. Além disso, verifique os Origin e Referer cabeçalhos em requisições sensíveis – garanta que elas venham do seu domínio.
  • Evite Usar GET para Mudanças de Estado: CSRF pode usar <img> ou <script> tags para iniciar requisições GET. Garanta que qualquer ação crítica (como modificar dados) use POST (ou outros métodos não-GET), e idealmente ainda exija um token.

Embora CSRF seja mais sobre design do que um bug de código, o kit de ferramentas de segurança do Aikido ainda pode ajudar. Análise estática pode detectar rotas ou controladores que não possuem proteções CSRF se você estiver usando frameworks comuns (por exemplo, um middleware csrf() ausente em uma aplicação Express, ou nenhum módulo anti-CSRF em uso). O Aikido também pode escanear seus cabeçalhos de segurança HTTP e configurações de cookies (via análise dinâmica ou scripts de pipeline) para sinalizar atributos SameSite ou HttpOnly ausentes. Ao integrar essas verificações, o Aikido garante que os hábitos de codificação segura (como a implementação de tokens CSRF e flags de cookie apropriadas) sejam aplicados consistentemente em todo o seu projeto.

5. Injeção de NoSQL

Assim como os bancos de dados SQL tradicionais sofrem de injeção de SQL, aplicações JavaScript modernas que utilizam bancos de dados NoSQL (como MongoDB, CouchDB, etc.) podem ser vulneráveis à injeção de NoSQL. A injeção de NoSQL ocorre quando um atacante manipula entradas que são usadas em consultas NoSQL, permitindo-lhes alterar consultas, ignorar autenticação ou recuperar dados não autorizados. Como as consultas NoSQL frequentemente usam JSON ou objetos de consulta, a sintaxe é diferente da SQL – mas o conceito de injetar parâmetros de maneiras inesperadas ainda se aplica.

Exemplo real: Considere uma aplicação Node.js usando MongoDB para autenticação de usuário, com código como:

// insecure pseudo-codeUsers.findOne({ username: inputUser, password: inputPass })

Isso parece bom à primeira vista, mas as queries do MongoDB aceitam objetos e operadores especiais. Um atacante poderia enviar um payload JSON para inputPass como { "$ne": null }. A query se torna {username: "victim", password: { $ne: null } }, o que no Mongo significa “encontrar um usuário com o username ‘victim’ e uma senha que não seja nula” – essencialmente ignorando a verificação de senha porque $ne: null é sempre verdadeiro para um campo de senha real. Esse tipo de injeção de operador NoSQL é uma técnica conhecida para contornar formulários de login. A Web Security Academy da PortSwigger documenta como a injeção de NoSQL pode “permitir que um atacante ignore a autenticação, extraia ou altere dados, ou até mesmo execute código no servidor” em alguns casos.

Além do bypass de autenticação, a injeção de NoSQL pode ser usada para extrair dados. Por exemplo, injetando $regex ou outros operadores, atacantes podem enumerar registros de usuários ou despejar bancos de dados se a aplicação não for cuidadosa.

Mitigação:

  • Sanitização de Entrada: Não passe dados controlados pelo usuário diretamente para as queries do banco de dados. Sanitize as entradas – por exemplo, se estiver esperando um username do tipo string, garanta que seja uma string e que não contenha $ ou outros caracteres especiais. Alguns ORMs ou bibliotecas de driver possuem verificações ou modos integrados para prevenir a injeção de operadores (por exemplo, o Mongoose pode desabilitar $ chaves prefixadas por padrão).
  • Use Queries Parametrizadas / ORM: Usar um ORM ou um construtor de queries pode reduzir a exposição direta a queries brutas. Certifique-se de usar quaisquer recursos de parametrização disponíveis.
  • Autenticação e Lógica de Query: Não dependa de apenas uma condição para operações sensíveis. Para login, prefira um fluxo de trabalho que verifique a senha independentemente (após recuperar o usuário pelo username) em vez de uma única query grande que poderia ser manipulada.
  • Registro e Monitoramento: Tentativas de injeção de NoSQL frequentemente deixam rastros (por exemplo, padrões de query estranhos ou erros). Registre tentativas de login falhas e parâmetros de query inesperados; isso pode ajudar a detectar um ataque em andamento.

A análise estática do Aikido pode detectar padrões de risco como o uso de

findOne()

ou queries semelhantes com entrada de usuário não verificada. Por exemplo, a Aikido poderia sinalizar se detectar $ ou caracteres regex sendo concatenados em uma string de query, ou o uso de Users.findOne({ ... entrada do usuário ... }) sem sanitização. Além disso, a varredura dinâmica do Aikido (se você a empregar contra uma instância de desenvolvimento em execução) pode incluir testes específicos para injeção de NoSQL, semelhante a como ferramentas DAST testam para SQLi. Ao aproveitar essas ferramentas, os desenvolvedores recebem um aviso antecipado: “Ei, esta função de login pode estar vulnerável a uma injeção de NoSQL.” Corrigir isso cedo evita um bypass de autenticação potencialmente desastroso em produção.

6. Negação de Serviço por Expressão Regular (ReDoS)

Negação de Serviço por Expressão Regular (ReDoS) é uma vulnerabilidade onde um atacante fornece uma entrada especialmente elaborada para uma regex (expressão regular) que leva um tempo excepcionalmente longo para ser avaliada, monopolizando a CPU e causando efetivamente uma negação de serviço. O motor de regex do JavaScript (como muitos outros) pode apresentar retrocesso catastrófico em certos padrões. Isso é particularmente relevante para Node.js, onde um único thread lida com muitos clientes – uma regex travada pode bloquear todo o event loop. Vulnerabilidades de ReDoS foram encontradas em vários pacotes npm e frameworks. Por exemplo, uma falha de baixa gravidade, mas notável, foi descoberta no compilador de templates do Vue.js 2 (CVE-2024-9506): uma regex escrita incorretamente para análise de HTML poderia ser explorada por uma <textarea> ou <script> tag malformada para “causar atrasos significativos na análise de templates”. Da mesma forma, a popular path-to-regexp biblioteca (usada no roteamento do Express) teve um problema de ReDoS (CVE-2024-52798), e inúmeras bibliotecas de validação (para URLs, e-mails, etc.) tiveram CVEs de ReDoS ao longo dos anos.

Exemplo do mundo real: Imagine um servidor Node.js que usa uma regex para validar endereços de e-mail no cadastro de usuários. Um padrão de regex ingênuo (por exemplo, algo como \/(.+?)@(.+?)\.(.+)\/) pode retroceder catastroficamente em uma string de determinado comprimento e composição. Atacantes poderiam enviar uma string de e-mail extremamente longa como "aaaa....aaaa!" (com certos padrões) que faz com que a regex trabalhe por segundos ou mais, durante o qual o servidor pode não conseguir lidar com outras requisições. Em um caso, um ReDoS na validator.js validação de URL da biblioteca foi encontrado – uma entrada de URL elaborada de algumas dezenas de kilobytes fez o processo travar. Se um atacante automatizasse o envio de tais entradas em massa, eles poderiam efetivamente derrubar o serviço. A fundação OWASP observa que a maioria dos motores de regex são suscetíveis a esses tipos de casos extremos.

Mitigação:

  • Evite Regex Complexas para Entradas Não Confiáveis: Simplifique seus padrões de regex ou use abordagens sem retrocesso. Se possível, use bibliotecas integradas ou algoritmos verificados para tarefas comuns (por exemplo, use o parser de URL integrado do Node em vez de uma regex complexa para URLs).
  • Use Timeouts: Para casos críticos, você pode usar uma biblioteca de regex que suporte timeouts ou sandboxing. No Node, as RegExp operações são síncronas, mas você poderia executar o trabalho de regex em um worker thread separado, se necessário, para evitar o bloqueio do loop principal.
  • Limite o Comprimento da Entrada: Frequentemente, o ReDoS depende de strings de entrada muito grandes. Ao impor limites de comprimento razoáveis nas entradas (por exemplo, nenhum endereço de e-mail deve ter mais de 254 caracteres, conforme RFC), você reduz a viabilidade do ReDoS.
  • Revise e Teste Padrões: Existem ferramentas que podem analisar regex para potencial de retrocesso catastrófico. Incorpore-as na revisão de código para qualquer padrão complexo. Escreva casos de teste com entradas patológicas para ver como suas regexes se comportam sob estresse.

A análise de dependências se destaca aqui – o Aikido rastreia CVEs e fraquezas conhecidas em seus pacotes npm. Se você estiver usando um pacote com um ReDoS conhecido (por exemplo, uma versão vulnerável de um parser de data ou validador de URL), o Aikido irá alertá-lo para atualizar para uma versão corrigida. Para padrões de regex personalizados em seu código, o SAST do Aikido pode identificar literais de regex hard-coded ou new RegExp() uso e aplicar verificações heurísticas (por exemplo, sinalizando padrões com quantificadores excessivos ou grupos aninhados). Pode não capturar todas as regex maliciosas, mas combinado com a base de conhecimento do Aikido, pode alertar “Esta regex parece suspeitosamente exponencial.” Além disso, as ferramentas de teste do Aikido podem simular ataques de fuzzing; se um payload simples causar problemas de desempenho, você aprenderia sobre isso durante os testes, em vez de um pager às 2 da manhã.

7. Directory Traversal e Exposição de Arquivos

Vulnerabilidades de Directory traversal (ou path traversal) permitem que atacantes acessem arquivos no servidor que deveriam ser restritos, manipulando os caminhos dos arquivos. Em Node.js, isso frequentemente ocorre com bibliotecas ou código que servem arquivos estáticos, lidam com downloads de arquivos ou processam arquivos zip. Se a entrada do usuário for concatenada em caminhos de arquivo sem a sanitização adequada, um atacante pode usar sequências como ../ para sair do diretório pretendido. Por exemplo, uma vulnerabilidade no pacote node-static (um servidor de arquivos estáticos simples) foi descoberta, onde uma verificação inadequada na função servePath permitiu que um atacante solicitasse uma URL com .. e acessasse arquivos arbitrários (CVE-2023-26111). Uma prova de conceito demonstrou que um atacante poderia recuperar arquivos sensíveis como /root/.ssh/id_rsa codificando ../../../../../ na URL.

Exemplo do mundo real: Um cenário comum é uma aplicação Express usando express.static() ou uma rota de serviço de arquivos personalizada. Suponha que você tenha:

app.get('/download', (req, res) => {  const file = req.query.file;    res.sendFile(__dirname + '/uploads/' + file);});

Se não houver cuidado, um atacante pode chamar /download?file=../../etc/passwd e recuperar arquivos do sistema. Houve casos em que aplicações expuseram chaves ou arquivos de configuração inadvertidamente dessa forma. Mesmo ao usar bibliotecas, houve bugs: versões mais antigas do middleware estático do Express tinham problemas conhecidos de directory traversal em casos extremos (como URLs com pontos codificados). O tratamento de caminhos do core do Node no Windows também tinha uma peculiaridade de traversal (CVE-2025-27210) envolvendo nomes de dispositivos que poderiam ser abusados. Além da leitura de arquivos, a escrita de arquivos é outro ângulo (por exemplo, ataques de “Zip Slip” onde a extração de um arquivo zip escreve arquivos fora da pasta pretendida).

Mitigação:

  • Normalize e Valide Caminhos: Use path.normalize() e path.join() para resolver quaisquer sequências .. e então garanta que o caminho resolvido esteja dentro do diretório permitido. Por exemplo, após a resolução, rejeite a requisição se o arquivo estiver fora da sua pasta /uploads .
  • Evite Caminhos Diretamente Controlados pelo Usuário: Sempre que possível, não use diretamente a entrada do usuário como nomes de arquivo. Mapeie as entradas do usuário para caminhos de arquivo predefinidos. Por exemplo, se os usuários devem baixar apenas seus próprios arquivos, use um identificador e procure o nome do arquivo no lado do servidor, em vez de confiar em um parâmetro de nome de arquivo.
  • Privilégio Mínimo: Execute seus processos Node.js com privilégios mínimos. Se o aplicativo não tiver motivos para acessar diretórios fora de certas áreas, considere restrições em nível de SO ou containerização para limitar os danos que uma travessia poderia causar.
  • Mantenha as Bibliotecas Atualizadas: Se você usa bibliotecas de serviço de arquivos ou de descompactação, mantenha-se atualizado sobre seus patches de segurança. A node-static vulnerabilidade mencionada não tinha “correção” no pacote mais antigo, o que pode significar usar uma biblioteca alternativa ou adicionar seu próprio patch.

A varredura do Aikido pode detectar padrões comuns de travessia de diretório no código. Por exemplo, o uso de sendFile ou readFile com req.query ou req.params é um sinal de alerta que nossas regras de SAST podem destacar. O Aikido também faz referência cruzada a vulnerabilidades conhecidas – se seu projeto depende de uma versão de send ou node-static com um CVE para travessia de caminho, ele o solicitará a atualizar. Para equipes DevSecOps, a força do Aikido está em combinar esses sinais: imagine que ele sinalize seu trecho de código de serviço de arquivos como arriscado e e observa que você está usando uma biblioteca desatualizada para isso – esse insight pode impulsionar uma correção rápida (higienizar a entrada e atualizar a versão da biblioteca). Essencialmente, o Aikido atua como um revisor de segurança extra, examinando sua lógica de acesso a arquivos para que os atacantes não possam examinar seu sistema de arquivos.

8. Dependências Vulneráveis e Desatualizadas

Aplicações JavaScript modernas frequentemente incluem dezenas ou centenas de pacotes npm. Cada uma dessas dependências (e suas subdependências) pode abrigar vulnerabilidades conhecidas. O uso de bibliotecas desatualizadas é tão comum que constitui uma categoria de risco própria: versões inseguras de frameworks frontend, módulos Node ou bibliotecas de utilidade podem expor seu aplicativo a ataques, mesmo que seu próprio código esteja em ordem. O estudo da Claranet de 2024 encontrou 1.032 instâncias de bibliotecas JavaScript desatualizadas em 500 aplicativos, observando que “o uso de JavaScript desatualizado pode levar a XSS, ataques de Negação de Serviço e divulgação de informações sensíveis”. Em outras palavras, CVEs conhecidos em bibliotecas populares se traduzem diretamente em riscos para sua aplicação se você não as tiver atualizado.

Exemplos do mundo real:

  • Lodash: Biblioteca de utilidades extremamente popular. Múltiplos CVEs (conforme discutido anteriormente) afetaram o Lodash – falhas de poluição de protótipo (CVE-2018-16487, CVE-2019-10744, CVE-2020-8203) e até mesmo um problema de DoS de Expressão Regular em _.escapeRegExp. Aplicativos presos em versões antigas do Lodash herdaram essas vulnerabilidades.
  • jQuery: Once ubiquitous on the frontend. jQuery <3.5.0 had that XSS vulnerability where injecting <option> tags poderiam executar scripts. Se seu frontend ainda usa, por exemplo, jQuery 2.1 ou 3.4, você está carregando falhas de XSS conhecidas que atacantes estão explorando ativamente.
  • Express e outros: O próprio framework Express teve alguns CVEs (redirecionamentos abertos, negação de serviço via requisições malformadas, etc.). Pacotes menores, como moment (biblioteca de datas) teve um path traversal em certos usos (CVE-2022-24785), markdown-it teve um problema de XSS, e assim por diante. Mesmo o core do Node teve vulnerabilidades que exigiam correção (como os problemas de HTTP request smuggling e path traversal em 2022-2025).

O uso de componentes vulneráveis é um dos OWASP Top Ten (Sob “Uso de Componentes com Vulnerabilidades Conhecidas”). É essencialmente uma preocupação de supply chain: se você incorpora uma biblioteca, você também incorpora seus bugs.

Mitigação:

  • Análise de Dependências e Atualizações: Execute regularmente auditoria npm ou ferramentas similares para obter uma lista de vulnerabilidades conhecidas em suas dependências. Atualize os pacotes para versões corrigidas. Use ferramentas que o alertem quando novas vulnerabilidades forem encontradas nas bibliotecas que você utiliza.
  • Higiene do Lockfile: Mantenha seu package-lock.json (ou lockfile do Yarn) com cuidado. Evite ter problemas de dependência aninhadas e não resolvidas usando npm audit fix quando apropriado. Se uma sub-dependência for vulnerável e não for atualizada, considere overrides ou entre em contato com os mantenedores.
  • Dependências Mínimas: Não inclua pacotes que você não precisa. Cada dependência extra é outro potencial ponto fraco. Por exemplo, se você precisa apenas de uma pequena função, pode ser mais seguro implementá-la do que incorporar uma biblioteca de 30 funções que você terá que confiar e monitorar.
  • Monitore os Avisos de Segurança: Mantenha-se informado sobre os avisos de segurança no ecossistema Node/JS. Assine as listas de e-mail de segurança do Node ou os alertas do Dependabot do GitHub para seus repositórios.

É aqui que a análise de dependências do Aikido e as correções alimentadas por IA realmente se destacam. O Aikido verifica continuamente sua árvore de dependências contra um banco de dados de vulnerabilidades. Se uma nova CVE for divulgada para, digamos, Express ou Lodash, você receberá uma notificação e até mesmo uma sugestão de correção automática (por exemplo, “atualizar de Lodash 4.17.11 para 4.17.21 para corrigir CVE-2020-8203”). Ferramentas amigáveis ao desenvolvedor significam que não é apenas um relatório – o Aikido pode abrir um pull request com a versão atualizada. Além disso, a capacidade SafeChain do Aikido (um firewall incorporado no aplicativo para seu gerenciador de pacotes) pode impedir a instalação de pacotes maliciosos conhecidos. Ao integrar essas ferramentas, sua equipe pode reduzir drasticamente a janela de exposição desde a divulgação de uma vulnerabilidade de biblioteca até a sua remediação em seu aplicativo.

9. Pacotes NPM Maliciosos e Ataques à Supply chain

Nem todos os ataques vêm de erros de codificação – alguns vêm do código que você pensou que poderia confiar. O ecossistema npm tem sofrido ataques à supply chain onde atacantes subvertem o fornecimento de pacotes para inserir código malicioso. Isso pode acontecer através de técnicas como typosquatting (publicar um pacote com um nome similar a um popular, esperando que alguém digite errado ou o instale por engano), ou comprometendo mantenedores de projetos legítimos. Um incidente infame foi o ataque event-stream em 2018: um atacante convenceu o mantenedor de event-stream (um pacote amplamente utilizado) a entregar o controle, então lançou uma nova versão que incluía uma dependência oculta (flatmap-stream) contendo malware. Ao longo de alguns meses, essa atualização maliciosa foi baixada milhões de vezes, e ela visava especificamente um aplicativo de carteira Bitcoin (Copay) para roubar chaves de criptomoeda.

Outros exemplos incluem pacotes como ua-parser-js, node-ipc, e event-source-polyfill que foram sequestrados por atacantes ou sabotados por seus próprios desenvolvedores para entregar cargas maliciosas (como spyware, mineradores de criptomoedas ou scripts destrutivos). Em 2021, pesquisadores de segurança demonstraram ataques de “confusão de dependência” – onde, se uma empresa usa um nome de pacote interno e um atacante publica um pacote com o mesmo nome no npm, as ferramentas de build podem puxar a versão do atacante. Esses cenários são particularmente perigosos porque podem dar aos atacantes execução remota de código durante seu build ou em produção, sem explorar nenhuma vulnerabilidade tradicional.

Mitigação:

  • Verifique a Autenticidade do Pacote: Use hashes de integridade de pacotes (o npm usa automaticamente package-lock com hashes sha512 para pacotes – mantenha esse lockfile commitado). Considere habilitar 2FA em contas npm e prefira pacotes de fontes confiáveis.
  • Proteja as Dependências Internas: Se você tem pacotes privados, garanta que seu registro ou processo de build não puxe acidentalmente do registro público. Use namespaces para pacotes internos ou utilize registros com escopo.
  • Monitore os Scripts de Instalação: Fique atento a pacotes que possuem scripts de install/post-install. Audite o que esses scripts fazem (alguns pacotes maliciosos os utilizam para executar comandos prejudiciais na instalação).
  • Use Ferramentas de Segurança: Aproveite o audit do npm e outras ferramentas para identificar anomalias. Por exemplo, se um pacote amplamente utilizado de repente lança uma nova versão menor após um longo período de inatividade, trate-o com escrutínio (como foi o caso com o lançamento 3.3.6 do event-stream).
  • Princípio do Menor Privilégio: Ao executar builds ou CI, execute-os em ambientes isolados (sandboxed). Para produção, considere mecanismos como o do Node --experimental-policy para controlar quais módulos podem require o quê, ou a conteinerização para limitar danos.

O Aikido ajuda a proteger sua segurança da supply chain de software. O Aikido SafeChain, por exemplo, pode analisar metadados de pacotes e até mesmo o conteúdo do pacote em busca de indicadores maliciosos. Ele pode bloquear a instalação de pacotes conhecidos por estarem comprometidos ou que exibam comportamento suspeito (como scripts pós-instalação ofuscados). O feed de Threat Intelligence do Aikido monitora malwares em pacotes de código aberto, então se amanhã uma biblioteca popular for sequestrada, o Aikido pode avisá-lo ou impedir atualizações para a versão comprometida. Além disso, o SAST do Aikido pode detectar o uso de operações sensíveis em dependências (como se uma dependência de repente começar a executar comandos shell ou acessar a rede de forma inesperada). Ao integrar essas ferramentas em seu pipeline, você adiciona uma forte camada de defesa contra o próximo ataque no estilo event-stream – essencialmente tendo um revisor de código automatizado para código de terceiros.

10. Secrets Hardcoded e Credenciais Expostas

Hardcodar Secrets (chaves de API, tokens, senhas) em seu código JavaScript ou configuração é uma prática arriscada que, infelizmente, permanece comum. No código frontend, qualquer Secret (por exemplo, uma chave de API para um serviço de terceiros) é visível para o usuário final e deve ser tratado como público – mas os desenvolvedores às vezes esquecem isso e deixam tokens sensíveis no bundle JS. Em código backend Node.js ou arquivos de configuração, os Secrets podem ser commitados no git e acabar no controle de versão ou no pacote implantado. A exposição de Secrets pode levar a acesso não autorizado, tomada de conta ou contas caras (por exemplo, se um atacante encontrar uma chave de API de um provedor Cloud, ele pode provisionar recursos ou despejar seus bancos de dados).

A escala deste problema é destacada por pesquisas: somente em 2024, quase 23,8 milhões de novos Secrets hardcoded foram detectados em commits públicos do GitHub, um aumento de 25% em relação ao ano anterior. Violações de alto perfil ocorreram devido a credenciais vazadas – por exemplo, um vazamento de credenciais do New York Times e outro na Sisense foram rastreados até a proliferação de Secrets. Mesmo em imagens Docker, milhares de chaves de API foram encontradas inadvertidamente incorporadas. A conclusão: a exposição de Secrets é desenfreada e muitas vezes a maneira mais fácil para os atacantes entrarem sem explorar um bug de software.

Exemplo do mundo real: Em 2019, um desenvolvedor acidentalmente enviou uma string de conexão MongoDB (com credenciais) para um repositório público do GitHub. Em questão de horas, atacantes que escaneavam o GitHub a encontraram, acessaram o banco de dados e mantiveram os dados para resgate. Em outro caso, desenvolvedores de aplicativos móveis deixaram uma chave privada do Firebase no JavaScript do aplicativo – atacantes a extraíram e acessaram dados de usuários no Firebase. Esses exemplos mostram que, seja em um arquivo .js arquivo, um .env arquivo commitado por engano, ou em qualquer lugar do seu codebase, Secrets são alvos fáceis para atacantes se expostos.

Mitigação:

  • Nunca codifique Secrets diretamente: Use variáveis de ambiente ou um serviço de gerenciamento de secrets. Seu aplicativo Node.js pode ler de process.env em tempo de execução, em vez de ter o secret no código-fonte. Para necessidades de frontend, considere proxyar requisições através do seu backend para que o secret não seja exposto, ou use fluxos OAuth que não exijam a incorporação de secrets.
  • Git Ignore e Varredura: Não faça commit de .env arquivos ou outros arquivos contendo secrets. Use .gitignore para excluí-los. Além disso, use ferramentas de varredura de secrets (o GitHub possui um scanner de secrets integrado para repositórios públicos, e ferramentas de terceiros podem escanear commits) para capturar qualquer secret que possa ter sido incluído.
  • Rotacione as Chaves: Em caso de qualquer suspeita de vazamento de um secret, rotacione-o imediatamente. Tenha um plano para rotação de chaves e use credenciais separadas para diferentes ambientes (para que um vazamento em dev não comprometa a produção, por exemplo).
  • Cofres e Gerenciamento de Configurações: Use um cofre de secrets adequado ou um gerenciador de secrets na Cloud para armazenar e buscar secrets em tempo de execução, em vez de armazená-los em arquivos de configuração.

O Aikido inclui recursos de detecção de segredos que verificam continuamente seu código e configurações em busca de padrões de credenciais. Por exemplo, se alguém acidentalmente fizer commit de uma chave de acesso AWS ou um token de API, o Aikido o sinalizará (mesmo durante um pull request) com um alerta de alta prioridade. Ele reconhece padrões e também pode usar o contexto (por exemplo, uma string hexadecimal de 40 caracteres em um arquivo de configuração pode ser sinalizada como uma chave de API potencial). Além disso, a plataforma do Aikido pode se integrar ao controle de versão para evitar que Secrets cheguem à produção – capturando-os no pipeline de CI. Isso é semelhante a ter um guardião que verifica “Tem certeza de que deseja fazer commit dessa chave?”. No caso de um Secret ser encontrado, o Aikido pode ajudar a avaliar o impacto identificando onde esse Secret pode ter se propagado e até mesmo sugerindo a remediação (como quais chaves rotacionar). Ao empregar tais ferramentas, os desenvolvedores podem fazer commit em repositórios com a confiança de que não estão publicando inadvertidamente as chaves do reino.

Conclusão

A força do JavaScript – sua ubiquidade e flexibilidade do navegador ao backend – é exatamente o que torna sua segurança uma tarefa tão crítica. Vimos como um simples descuido (uma saída não sanitizada, um pacote desatualizado, uma chave de API vazada) pode facilmente desvendar a segurança de uma aplicação. A boa notícia é que a conscientização e as melhores práticas são muito eficazes: ao entender essas principais vulnerabilidades, os desenvolvedores podem evitar erros comuns como avaliar dados não confiáveis ou deixar uma porta aberta via ../ em um caminho. Adotar uma mentalidade de segurança em primeiro lugar significa validar entradas, codificar saídas, atualizar dependências e nunca presumir “ninguém notará meu erro” – porque se você não o detectar, um atacante eventualmente o fará.

Incorpore a segurança em seu fluxo de trabalho de desenvolvimento. Adote hábitos de codificação segura (revise as folhas de dicas da OWASP, use linters e type-checkers para identificar problemas cedo). E aproveite ferramentas de segurança integradas que trabalham ao seu lado – desde análise estática de código até auditoria de dependências e varredura de segredos. Soluções como Aikido permitem que você incorpore essas práticas em seu pipeline de CI/CD, para que cada commit e build seja verificado automaticamente em busca de vulnerabilidades. Ao identificar problemas cedo e com frequência, você reduz o risco sem desacelerar. O mundo do JavaScript se move rápido, mas com as salvaguardas certas, você pode inovar tão rápido sem deixar seu aplicativo exposto. Entregue com confiança e segurança – seus usuários e sua equipe de DevSecOps agradecerão!

Continue lendo:
As 9 principais vulnerabilidades de segurança de Container Docker    
As 7 principais vulnerabilidades de segurança na Cloud    
As 10 principais vulnerabilidades de segurança de aplicações web que toda equipe deve conhecer    
As 9 principais vulnerabilidades e configurações incorretas de segurança Kubernetes    
As principais vulnerabilidades de segurança de código encontradas em aplicações modernas    
As 10 principais vulnerabilidades de segurança Python que os desenvolvedores devem evitar    As 9 principais vulnerabilidades de segurança da supply chain de software explicadas

4.7/5

Proteja seu software agora

Comece Gratuitamente
Não é necessário cc
Agendar uma demonstração
Seus dados não serão compartilhados · Acesso somente leitura · Não é necessário cartão de crédito

Inscreva-se para receber notícias sobre ameaças.

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.