10 práticas recomendadas de segurança para npm
Juan Picado
19 de fevereiro de 2019
0 minutos de leituraPreocupado com vulnerabilidades no npm? É importante que desenvolvedores de frontend e backend adotem práticas recomendadas de segurança para npm. A auditoria de segurança de código aberto é essencial para antecipar a segurança no ciclo de desenvolvimento, e a segurança dos pacotes npm deve ser uma prioridade, já que até mesmo a ferramenta oficial de linha de comando do npm já foi identificada como vulnerável.
Nesta edição do nosso guia prático, vamos nos concentrar em dez práticas recomendadas de segurança para npm e dicas de produtividade para mantenedores de projetos de código aberto e desenvolvedores. Então, vamos à nossa lista de 10 práticas recomendadas de segurança para npm, começando por um erro clássico: pessoas que adicionam suas senhas aos pacotes npm que publicam!
1. Evite publicar segredos no registro do npm
Seja usando chaves de API, senhas ou outros segredos, eles podem acabar facilmente no controle de versão do código-fonte ou até mesmo em um pacote publicado no registro público do npm. Talvez você tenha segredos no diretório de trabalho, em arquivos específicos como .env, que devem ser adicionados a um .gitignore para evitar o envio a um SCM. Mas o que acontece quando você publica um pacote npm a partir do diretório do projeto?
A CLI do npm empacota o projeto em um arquivo tar (tarball) para enviá-lo ao registro. Os seguintes critérios determinam quais arquivos e diretórios são incluídos no tarball:
Se houver um arquivo
.gitignoreou.npmignore, seu conteúdo será usado como padrão de exclusão ao preparar o pacote para publicação.Se os dois arquivos de exclusão existirem, tudo o que não estiver em
.npmignoreserá publicado no registro. Essa condição costuma gerar confusão e pode levar ao vazamento de segredos. Desenvolvedores podem atualizar o arquivo.gitignore, mas esquecer de atualizar também o.npmignore. Com isso, um arquivo potencialmente confidencial pode não ser enviado ao controle de versão, mas ainda assim ser incluído no pacote npm.
Outra boa prática é usar a propriedade files no package.json. Ela funciona como uma lista de permissões e especifica o conjunto de arquivos que será incluído no pacote criado e instalado (enquanto o arquivo de exclusão funciona como uma lista de bloqueio). A propriedade files e um arquivo de exclusão podem ser usados em conjunto para determinar quais arquivos devem ser incluídos ou excluídos explicitamente do pacote. Quando ambos são usados, a propriedade files no package.json tem precedência sobre o arquivo de exclusão.
Ao publicar um pacote, a CLI do npm mostra detalhadamente o arquivo que está sendo criado. Para ter ainda mais cuidado, adicione o argumento --dry-run ao comando de publicação. Assim, você pode conferir como o tarball será criado sem publicá-lo no registro.
Em janeiro de 2019, o npm anunciou em seu blog que havia adicionado um mecanismo que revoga automaticamente um token caso detecte que ele foi publicado junto com um pacote.
2. Exija o uso do arquivo de bloqueio
Recebemos de braços abertos o surgimento dos arquivos de bloqueio de pacotes, que trouxeram instalações determinísticas em diferentes ambientes e garantiram dependências consistentes entre os membros da equipe. Tudo certo! Ou assim pensei… O que teria acontecido se eu tivesse alterado o arquivo package.json do projeto, mas esquecido de enviar o arquivo de bloqueio junto com ele?
Yarn e npm se comportam da mesma forma durante a instalação de dependências. Quando detectam uma inconsistência entre o package.json do projeto e o arquivo de bloqueio, eles compensam a alteração com base no manifesto package.json, instalando versões diferentes das registradas no arquivo de bloqueio.
Essa situação pode ser perigosa para ambientes de build e produção, pois eles podem obter versões de pacotes não pretendidas, anulando todo o benefício de um arquivo de bloqueio.
Felizmente, é possível orientar o Yarn e o npm a seguir um conjunto específico de dependências e versões, consultando o arquivo de bloqueio. Qualquer inconsistência interromperá a instalação. Use os seguintes comandos:
Se você usa Yarn, execute
yarn install --frozen-lockfile.Se você usa npm, execute
npm ci.
3. Reduza a superfície de ataque ignorando scripts de execução
A CLI do npm trabalha com scripts de execução de pacotes. Se você já executou npm start ou npm test, também já usou esses scripts. A CLI do npm se baseia em scripts que podem ser declarados por um pacote e permite que eles sejam executados em pontos específicos durante a instalação do pacote em um projeto. Por exemplo, algumas dessas entradas de gancho de script podem ser scripts postinstall, executados pelo pacote instalado para realizar tarefas de manutenção.
Com esse recurso, agentes mal-intencionados podem criar ou alterar pacotes para realizar ações maliciosas, executando qualquer comando quando o pacote é instalado. Já vimos isso acontecer em casos como o incidente do popular eslint-scope, que coletou tokens do npm, e o incidente do crossenv, além de outros 36 pacotes que exploraram ataques de typosquatting no registro do npm.
Adote estas práticas recomendadas de segurança para npm e reduza a superfície de ataque de módulos maliciosos:
Sempre avalie cuidadosamente os módulos de terceiros que você instala e faça a devida diligência para confirmar que são confiáveis e estão em boas condições.
Evite atualizar às cegas para novas versões. Espere um pouco para que as novas versões dos pacotes circulem antes de experimentá-las.
Antes de atualizar, confira o changelog e as notas da versão para a qual você está atualizando.
Ao instalar pacotes, adicione o sufixo
--ignore-scriptspara desativar a execução de scripts de pacotes de terceiros.Considere adicionar
ignore-scriptsao arquivo de projeto.npmrcou à configuração global do npm.
4. Avalie a integridade do projeto npm
Dependências desatualizadas
Atualizar as dependências constantemente para as versões mais recentes não é necessariamente uma boa prática se isso for feito sem analisar as notas da versão e as alterações no código, nem testar as atualizações de forma abrangente. Por outro lado, deixar as dependências desatualizadas sem atualizá-las — ou esperar muito tempo para isso — também pode causar problemas.
A CLI do npm pode informar o quanto suas dependências estão atualizadas, considerando as faixas de versões semânticas. Ao executar npm outdated, você verá quais pacotes estão desatualizados:

"As dependências em amarelo correspondem à faixa de versões semânticas especificada no manifesto package.json, e as dependências em vermelho indicam que há uma atualização disponível. A saída também mostra a versão mais recente de cada dependência.
Chame o médico
Com a variedade de gerenciadores de pacotes Node.js e as diferentes versões do Node.js que você pode ter no caminho de execução, como verificar se a instalação do npm e o ambiente estão funcionando bem? Seja usando a CLI do npm em um ambiente de desenvolvimento ou em um CI, é importante confirmar que tudo está funcionando como esperado.
Chame o médico! A CLI do npm inclui uma ferramenta de avaliação da integridade que diagnostica seu ambiente e verifica se o npm está funcionando corretamente. Execute npm doctor para verificar sua configuração do npm:
Verifica se o registro oficial do npm está acessível e mostra qual registro está configurado no momento.
Verifica se o Git está disponível.
Confere as versões instaladas do npm e do Node.js.
Verifique as permissões de várias pastas, como as pastas
node_moduleslocal e global, e da pasta usada para o cache de pacotes.Verifica se as somas de verificação do cache local de módulos do npm estão corretas.
5. Audite vulnerabilidades em dependências de código aberto
O ecossistema npm é o maior repositório de bibliotecas para aplicações entre todos os ecossistemas de linguagens. O registro e as bibliotecas disponíveis nele são essenciais para desenvolvedores JavaScript, que podem aproveitar o trabalho já realizado por outras pessoas e incorporá-lo à própria base de código. No entanto, o uso cada vez maior de bibliotecas de código aberto em aplicações também aumenta o risco de introduzir vulnerabilidades de segurança.
Muitos pacotes npm populares já foram identificados como vulneráveis e podem representar riscos significativos sem uma auditoria de segurança adequada das dependências do seu projeto. Alguns exemplos são npm request, superagent, mongoose e até pacotes relacionados à segurança, como jsonwebtoken e npm validator.
A segurança não se resume a verificar vulnerabilidades ao instalar um pacote. Para ser adotada com eficácia ao longo de todo o ciclo de desenvolvimento de software, ela também deve estar integrada aos fluxos de trabalho dos desenvolvedores e ser monitorada continuamente quando o código é implantado.
Verifique se há vulnerabilidades
Adote práticas recomendadas de segurança para npm e use o Snyk para verificar se há vulnerabilidades:
Ao executar um teste do Snyk, ele informa as vulnerabilidades encontradas e mostra os caminhos vulneráveis, para que você possa acompanhar a árvore de dependências e entender qual módulo introduziu uma vulnerabilidade. Mais importante ainda, o Snyk oferece orientações práticas para corrigir o problema: você pode atualizar para uma versão corrigida por meio de um pull request automatizado que o Snyk abre no seu repositório ou aplicar um patch fornecido pelo Snyk para mitigar a vulnerabilidade, caso ainda não haja uma correção disponível. O Snyk recomenda uma atualização inteligente para a menor versão semântica possível que corrija a vulnerabilidade do pacote.
Monitore vulnerabilidades encontradas em bibliotecas de código aberto
O trabalho de segurança não termina aí.
E quanto às vulnerabilidades encontradas em uma dependência da aplicação depois que ela já foi implantada? É aí que o monitoramento de segurança e a integração estreita com o ciclo de desenvolvimento do projeto se tornam essenciais.
Recomendamos integrar o Snyk ao seu sistema de gerenciamento de código-fonte (SCM), como GitHub ou GitLab, para que o Snyk monitore seus projetos ativamente e:
Abra automaticamente PRs para atualizar ou corrigir dependências vulneráveis para você
Verifique e detecte vulnerabilidades em bibliotecas de código aberto que possam ter sido introduzidas por um pull request
Se não for possível integrar o Snyk a um SCM, você também pode monitorar snapshots dos seus projetos enviados pela ferramenta Snyk CLI. Basta executar:
Qual é a diferença entre o Snyk e o npm audit?
Confira uma publicação no blog da Nearform que compara as diferenças entre o audit do npm e o Snyk.
O banco de dados de vulnerabilidades do Snyk oferece informações abrangentes sobre vulnerabilidades por meio de seu sistema de inteligência contra ameaças. Ele proporciona uma cobertura melhor e identifica e relata vulnerabilidades que ainda não receberam um CVE. Por exemplo, 72% das vulnerabilidades nos avisos do npm foram adicionadas primeiro ao banco de dados de vulnerabilidades de código aberto do Snyk Open Source.
6. Use um proxy npm local
O registro do npm é a maior coleção de pacotes disponível para desenvolvedores JavaScript e também abriga a maioria dos projetos de código aberto para desenvolvimento web. Mas, às vezes, você pode ter necessidades diferentes em relação à segurança, à implantação ou ao desempenho. Nesses casos, o npm permite que você use outro registro:
Ao executar npm install, o npm se comunica automaticamente com o registro principal para resolver todas as suas dependências. Se quiser usar outro registro, é muito simples:
Use
npm set registrypara configurar um registro padrão.Use o argumento
--registrypara especificar um único registro.
O Verdaccio é um registro privado simples, leve e que não exige configuração. Instalá-lo é muito fácil:

Nunca foi tão fácil hospedar seu próprio registro! Confira os recursos mais importantes desta ferramenta:
Ela é compatível com o formato de registro do npm, incluindo recursos para pacotes privados, suporte a escopos, controle de acesso a pacotes e usuários autenticados na interface web.
Ela permite conectar registros remotos e direcionar cada dependência para diferentes registros, além de armazenar tarballs em cache. Para reduzir downloads duplicados e economizar largura de banda nos servidores de desenvolvimento local e CI, faça proxy de todas as dependências.
Por padrão, ela usa a segurança htpasswd como provedor de autenticação, mas também oferece suporte a Gitlab, Bitbucket e LDAP. Você também pode usar seu próprio provedor.
É fácil escalar usando outro provedor de armazenamento.
Se seu projeto usa Docker, a melhor opção é usar a imagem oficial.
Ela permite inicializar ambientes de teste com muita rapidez e é útil para testar projetos com grandes monorepos.
É bem simples de executar:
Se você usa o verdaccio para um registro privado local, considere configurar seus pacotes para exigir a publicação no registro local e evitar que desenvolvedores publiquem por engano em um registro público. Para isso, adicione o seguinte ao package.json:
Seu registro está no ar — oba! Agora, para publicar um pacote, basta executar o comando npm npm publish e pronto: você já pode compartilhá-lo com o mundo.
7. Divulgue vulnerabilidades de segurança com responsabilidade
Quando vulnerabilidades de segurança são encontradas, elas podem representar uma ameaça séria se forem divulgadas publicamente sem aviso prévio ou sem medidas de mitigação adequadas para que os usuários possam se proteger.
Recomenda-se que pesquisadores de segurança sigam um programa de divulgação responsável, ou seja, um conjunto de processos e diretrizes que busca conectar os pesquisadores ao fornecedor ou responsável pela manutenção do ativo vulnerável. O objetivo é comunicar a vulnerabilidade, seu impacto e sua aplicabilidade. Depois que a vulnerabilidade é devidamente avaliada, o fornecedor e o pesquisador coordenam uma correção e a data de divulgação, para oferecer aos usuários afetados um caminho de atualização ou remediação antes que o problema de segurança se torne público.
Segurança é importante demais para ser deixada para depois ou tratada de forma antiética. Na Snyk, valorizamos muito a comunidade de segurança e acreditamos que divulgar vulnerabilidades de segurança em pacotes open source com responsabilidade ajuda a garantir a segurança e a privacidade dos usuários.
A equipe de pesquisa de segurança da Snyk colabora regularmente com a comunidade em programas de recompensa por bugs, como no caso do f2e-server, que resultou em centenas de divulgações feitas pela comunidade. A Snyk também mantém uma parceria próxima com pesquisadores acadêmicos, como os da Virginia Tech, para oferecer experiência em segurança e coordenar ações com fornecedores e responsáveis pela manutenção da comunidade.
Convidamos você a colaborar conosco e oferecemos ajuda durante o processo de divulgação:
Envie divulgações responsáveis de problemas de segurança em https://snyk.io/vulnerability-disclosure ou pelo e-mail security@snyk.io
Nossa política de divulgação está disponível aqui.
8. Ative a autenticação de dois fatores (2FA)
Em outubro de 2017, o npm anunciou oficialmente o suporte à autenticação de dois fatores (2FA) para desenvolvedores que usam o registro do npm para hospedar pacotes privados e open source.
Embora o registro do npm ofereça suporte à 2FA há algum tempo, sua adoção parece lenta. Um exemplo disso foi o incidente com o eslint-scope em meados de 2018, quando o roubo da conta de um desenvolvedor da equipe do ESLint levou à publicação de uma versão maliciosa do eslint-scope por agentes mal-intencionados.
** ALERTA URGENTE DE SEGURANÇA ** Compartilhe.
Hoje, foi descoberto que a versão 3.7.2 do eslint-scope (https://t.co/Gkc9XhDRN6) contém código malicioso que rouba suas credenciais do NPM. Se você está usando a versão 3.7.2, tome uma providência agora.
Registro no banco de dados da Snyk: https://t.co/dAhhA3cZQP
— Snyk (@snyksec) 12 de julho de 2018
Ativar a 2FA é uma medida simples e importante para seguir as práticas recomendadas de segurança do npm. O registro oferece dois modos de ativação da 2FA na conta do usuário:
Somente autorização — quando o usuário entra no npm pelo site ou pela CLI, ou realiza outras ações, como alterar as informações do perfil.
Autorização e gravação — inclui ações de perfil e de login, além de ações de gravação, como gerenciar tokens e pacotes, e algumas ações relacionadas a informações de equipe e visibilidade de pacotes.
Tenha um aplicativo de autenticação, como o Google Authentication, instalado em um dispositivo móvel e você já pode começar. Uma forma simples de ativar a proteção adicional da 2FA na sua conta é pela interface do npm, que permite fazer isso com facilidade. Se você prefere a linha de comando, também é fácil ativar a 2FA usando uma versão compatível do cliente npm (>=5.5.1):
Siga as instruções da linha de comando para ativar a 2FA e salvar os códigos de autenticação de emergência. Se quiser ativar o modo 2FA apenas para login e alterações de perfil, substitua auth-and-writes por auth-only no código acima.
9. Use tokens de autoria do npm
Sempre que você entra usando a CLI do npm, é gerado um token para sua conta, que autentica seu acesso ao registro do npm. Os tokens facilitam a realização de ações relacionadas ao registro do npm durante processos de CI e automação, como acessar módulos privados no registro ou publicar novas versões em uma etapa de build.
É possível gerenciar tokens no site do registro do npm ou usando o cliente de linha de comando do npm. Veja um exemplo de como usar a CLI para criar um token somente de leitura, restrito a um intervalo específico de endereços IPv4:
Para verificar quais tokens foram criados para sua conta ou revogar tokens em caso de emergência, use npm token list ou npm token revoke, respectivamente.
Siga esta prática recomendada de segurança do npm: proteja seus tokens e reduza ao mínimo sua exposição.
10. Entenda as convenções de nomenclatura de módulos e os ataques de typosquatting
Dar nome a um módulo pode ser a primeira coisa que você faz ao criar um pacote. Mas, antes de definir o nome final, confira as regras que o npm estabelece para os nomes dos pacotes:
O limite é de 214 caracteres
Não pode começar com ponto ou sublinhado
Não pode conter letras maiúsculas
Não pode terminar com espaços
Use apenas letras minúsculas
Alguns caracteres especiais não são permitidos: “~\’!()*”)’
Não pode começar com . ou _
Não pode usar node_modules nem favicon.ico, pois esses nomes são proibidos
Mesmo seguindo essas regras, saiba que o npm usa um mecanismo de detecção de spam ao publicar pacotes novos, com base em uma pontuação e na conformidade do nome do pacote com os termos de serviço. Se as condições forem violadas, o registro poderá negar a solicitação.
Typosquatting é um tipo de ataque que se aproveita de erros cometidos pelos usuários, como erros de digitação. Nesse tipo de ataque, agentes mal-intencionados podem publicar módulos maliciosos no registro do npm com nomes muito parecidos com os de módulos populares já existentes.
Temos acompanhado dezenas de pacotes maliciosos no ecossistema do npm; casos semelhantes também foram identificados no registro Python PyPi. Alguns dos incidentes mais conhecidos envolveram cross-env, event-stream e eslint-scope.

As credenciais dos usuários são um dos principais alvos dos ataques de typosquatting, pois qualquer pacote tem acesso às variáveis de ambiente por meio da variável global process.env. Outro caso que vimos foi o do event-stream, em que o ataque tinha como alvo os desenvolvedores e buscava injetar código malicioso no código-fonte de um aplicativo.
Para encerrar nossa lista de dez práticas recomendadas de segurança do npm, veja algumas dicas para reduzir o risco desses ataques:
Tenha muito cuidado ao copiar e colar instruções de instalação de pacotes no terminal. Confira no repositório do código-fonte e no registro do npm se esse é realmente o pacote que você pretende instalar. Você pode verificar os metadados do pacote com
npm infopara obter mais informações sobre os colaboradores e as versões mais recentes.Por padrão, use o npm sem estar conectado nas tarefas do dia a dia, para que suas credenciais não se tornem o ponto fraco que poderia facilitar o comprometimento da sua conta.
Ao instalar pacotes, acrescente
--ignore-scriptspara reduzir o risco de execução de comandos arbitrários. Por exemplo:npm install my-malicious-package --ignore-scripts
Não deixe de imprimir o guia de referência rápida e fixá-lo em algum lugar para lembrar algumas das práticas recomendadas de segurança do npm que você deve seguir se desenvolve em JavaScript ou simplesmente gosta de usar o npm.
Comece a resolver desafios de capture the flag
Aprenda a resolver desafios de capture the flag assistindo sob demanda ao nosso workshop virtual introdutório.