Principais conclusões
- O Moment e o Moment Timezone são projetos legados em modo de manutenção, e novos trabalhos devem utilizar alternativas.
- O fato de um software ser considerado obsoleto não implica em sua remoção imediata, nem torna todas as instalações vulneráveis.
- As migrações que abandonam o Moment ocorrem com muito mais frequência devido à mutabilidade e à análise flexível do que por questões de sintaxe.
- Escolha um substituto com base no fuso horário e no comportamento de análise de que você precisa, e não em testes de desempenho relacionados ao tamanho do pacote.
O Moment é uma das poucas bibliotecas que publicamente pediu aos usuários que parassem de usá-la. O projeto declarou seu status de legado e entrou em modo de manutenção já em 2020; sua página no npm ainda o identifica como um projeto legado que não está recebendo novos recursos, e o README do Moment Timezone vai além, aconselhando a maioria das pessoas a escolher uma biblioteca diferente. Isso não significa o fim da vida útil do produto no papel. Para uma equipe presa à versão 2.24.0, porém, o problema prático se parece muito com isso, pois as correções do desenvolvedor original chegam à versão atual do Moment e ninguém as retroporta para uma versão tão antiga.
A complicação é que substituir o Moment não é um mero exercício de sintaxe. Seus objetos são mutáveis e sua análise sintática é tolerante de maneiras que as alternativas modernas deliberadamente não são; portanto, uma migração mal feita resulta em datas incorretas, em vez de erros de compilação.
A Moment resolveu o problema antes mesmo de a plataforma estar pronta
O Moment.js surgiu numa época em que lidar com datas em JavaScript era realmente complicado. A análise e a formatação variavam de um motor para outro, os cálculos de fuso horário eram uma incógnita e formatar uma data sem uma biblioteca auxiliar significava ter que fazer manualmente a manipulação de strings — algo que ninguém queria assumir. O Moment resolveu isso e o fez tão bem que se tornou o padrão por boa parte de uma década. Considerar sua idade como um fracasso é entender a história ao contrário. Ele resolveu um problema real antes que a plataforma estivesse pronta para isso.
É isso que torna a experiência atual tão estranha. Você abre a página do pacote para verificar uma versão, e o arquivo README é exibido com um aviso de que se trata de um projeto legado em modo de manutenção. Em seguida, você faz uma busca nos seus próprios repositórios e descobre que o Moment está presente em três deles.
É fácil interpretar o “modo de manutenção” como um leve incentivo a algo mais novo. Mas isso é perder o foco. Trata-se de uma declaração sobre o que será corrigido e o que não será; e, quando você entende dessa forma, a versão fixada na sua package.json começa a parecer diferente.
O Moment.js está obsoleto? E o que significa “modo de manutenção”?
Não no sentido estrito. Não há nenhum anúncio com data definida para o fim da vida útil nem um commit de encerramento. O que o projeto fez foi se autodenominar um projeto legado em modo de manutenção e desencorajar novas adoções, o que é uma resposta mais precisa e útil do que um simples sim ou não.
Os mantenedores são claros quanto aos limites e os redefiniram em agosto de 2026 pela primeira vez desde 2020. O Moment continuará a tratar de questões críticas de segurança, e as atualizações dos dados de fuso horário do Moment continuarão a acompanhar os lançamentos da IANA. Ele ainda não incorporará novos recursos voltados para o usuário e não está redesenhando a API mutável. O que mudou foi o escopo. A política de 2020 descartou qualquer trabalho relacionado ao tamanho do pacote e ao “tree shaking”, bem como qualquer versão 3. A atualização de 2026 amplia esse escopo, permitindo que os mantenedores se dediquem à empacotamento, às declarações do TypeScript, às ferramentas de compilação e à composição do pacote.
E isso não foi só conversa. A versão 2.31.0 foi lançada em 14 de setembro de 2026, trazendo uma correção de segurança, uma longa lista de correções de bugs e atualizações de localização — o primeiro lançamento desde a versão 2.30.1, no final de 2023.
O projeto também voltou atrás em relação à promessa feita em 2020 de nunca lançar uma versão 3. Não há um cronograma para a versão 3.0, e qualquer versão 3.0 ainda seria uma versão de manutenção, em vez de um retorno ao desenvolvimento de novos recursos; porém, a porta que havia sido soldada em 2020 agora está apenas fechada. Esse é o limite atual, e ele está um pouco mais aberto do que estava há seis anos.
O Moment é mantido pela OpenJS Foundation como um projeto At-Large, portanto, conta com uma estrutura de governança neutra e uma política de segurança publicada. Nenhum desses aspectos prevê o financiamento de retroportações para ramos de versões antigas. Qualquer correção de segurança implementada é feita no código atual.
A realidade: para uma equipe que permanece na versão 2.24.0, o modo de manutenção gera um problema de suporte relacionado ao fim da vida útil (EOL). O trabalho de segurança do projeto original tem como alvo a versão atual do Moment; portanto, o horizonte prático de suporte para a sua versão chegou ao fim há anos, mesmo que o projeto em si continue bem ativo.
O histórico do CVE é curto e fica exatamente onde você realmente o utiliza
O número de vulnerabilidades do Moment é pequeno, o que é uma boa notícia. O problema é que todas as entradas estão no código que lida com entradas do usuário (análise de datas, análise de durações e carregamento de configurações regionais), e esses são exatamente os caminhos pelos quais os aplicativos costumam enviar dados do usuário.
| CVE | Tipo | Versões afetadas | Corrigido em | CVSS |
|---|---|---|---|---|
| CVE-2022-31129 | ReDoS na análise do RFC 2822 | 2.18.0 a 2.29.3 | 2.29.4 | 7,5 Alto |
| CVE-2022-24785 | Percorrimento de caminho por meio da configuração regional | 1.0.1 a 2.29.1 | 2.29.2 | 7,5 Alto |
| CVE-2017-18214 | ReDoS em análises sintáticas mais antigas | antes da versão 2.19.3 | 2.19.3 | 7,5 Alto |
| CVE-2016-4055 | ReDoS na análise de duração | antes da versão 2.11.2 | 2.11.2 | 6,5 Médio |
O CVE-2022-31129 apresenta um comportamento quadrático (N²) em preprocessRFC2822 quando remove comentários legados de uma string de data. Se for fornecida uma entrada longa o suficiente, a análise fica paralisada, o que constitui uma técnica simples de negação de serviço. CVE-2022-24785 é um traversal de caminho por meio de uma string de localidade fornecida pelo usuário, usada para alterar a localidade do Moment, corrigido na versão 2.29.2. CVE-2017-18214 é um ReDoS anterior nas expressões regulares de análise de versões mais antigas, e CVE-2016-4055 é um ReDoS relacionado em duration(), corrigido na versão 2.11.2.
A questão que determina a gravidade em sua aplicação é específica. Uma entrada controlada pelo invasor pode chegar ao construtor do Moment, moment.duration(), ou o seletor de localidade, e o que verifica isso na entrada? Se nada não confiável chegar a esses caminhos, sua exposição real é menor do que a pontuação bruta sugere.
Cuidado: Limite o comprimento de qualquer string de data ou duração antes que ela chegue ao Moment. O próprio comunicado dos mantenedores sobre o CVE-2022-31129 sugere 200 caracteres, o que neutraliza a vulnerabilidade do RFC2822 e reduz drasticamente a exposição às outras duas. O mesmo comunicado afirma que um filtro como esse também ajuda a proteger contra a maioria das futuras vulnerabilidades do tipo ReDoS. No entanto, isso não resolve a vulnerabilidade relacionada à localidade. Para esses casos, apenas manualmente moment.locale() uma sequência de caracteres proveniente de uma lista de locales permitidos que você realmente distribui.
Suporte contínuo ao ciclo de vida do Moment.js pela TuxCare abrange as versões 2.0.0, 2.10.6 e 2.24.0, e todas as três estão abaixo das correções da série 2.29.x. A vulnerabilidade de traversal de caminho (CVE-2022-24785) afeta todas elas. Os CVEs de ReDoS se dividem de acordo com as versões. O ReDoS RFC2822 (CVE-2022-31129) se aplica apenas a partir da versão 2.18.0, portanto, afeta a versão 2.24.0, mas não as duas versões anteriores. O ReDoS de análise de sintaxe antiga (CVE-2017-18214) foi corrigido antes do lançamento da versão 2.24.0; portanto, são as versões 2.0.0 e 2.10.6 que apresentam essa vulnerabilidade. A vulnerabilidade ReDoS relacionada à duração (CVE-2016-4055) se restringe ainda mais e afeta apenas a versão 2.10.6. A versão 2.0.0 está dentro do intervalo publicado, mas sua duration() não analisa strings de forma alguma, portanto a expressão regular vulnerável simplesmente não existe.
A TuxCare já lançou patches para todas essas CVEs que se aplicam às versões suportadas por ela. Acesse o CVE Tracker para encontrar todas as vulnerabilidades e correções disponíveis no software de código aberto suportado pela TuxCare e em suas cadeias de dependências.
Escolher uma alternativa ao Moment.js é a parte fácil
Se você decidiu partir, a lista de opções é curta, e escolher uma delas é a parte mais rápida. A primeira opção é uma biblioteca que nunca sofre mutações no próprio objeto. Luxon e Day.js retornam novos objetos imutáveis, enquanto o date-fns opera sobre objetos simples Date valores e retorna novos. O segundo se baseia no recurso embutido Intl API para formatação e gerenciamento de configurações regionais. A terceira é a API Temporal nativa, que atingiu o Estágio 4 do TC39 em março de 2026 e já vem integrada ao Chrome, ao Edge e ao Firefox. O Safari, por enquanto, só a disponibiliza na versão Technology Preview, mas, assim que for implementada em todos os navegadores, o uso de uma biblioteca de terceiros se tornará opcional para muitos casos de uso.
A questão mais complicada é saber de quais comportamentos do Moment seu aplicativo depende no momento, pois isso determina o que deixará de funcionar quando você fizer a troca. Uma biblioteca que seja objetivamente melhor projetada ainda pode produzir resultados diferentes para as mesmas entradas que seu código vem fornecendo ao Moment há anos.
Considere o Moment Timezone como uma decisão à parte. Ele possui seu próprio pacote de dados de fuso horário e sua própria interface de API, e o código sensível ao fuso horário desenvolvido com base nele é a parte mais complexa do trabalho. O código que apenas formata datas é facilmente transferível. O código que realiza cálculos relacionados ao fuso horário em transições de horário de verão, por outro lado, não é.
A semântica de datas que prejudica as migrações
É nesse ponto que as migrações do Moment realmente falham. A estrutura da API é fácil de traduzir. A semântica subjacente, porém, não é.
Vamos começar pela mutabilidade. Os objetos do Moment sofrem alterações no próprio local, portanto .add() e .startOf() altere a instância na qual você os chamou. Um código que passa uma instância compartilhada do `Moment` e espera que cada chamada a modifique está dependendo desse comportamento, muitas vezes sem que ninguém perceba. O Luxon, o Day.js e o Temporal, por outro lado, retornam novos objetos, e as funções do `date-fns` retornam novos Date valores. Se você aplicar esse padrão de chamada diretamente, ele produzirá silenciosamente o resultado errado, em vez de gerar um erro, porque o valor que você pretendia alterar nunca foi alterado.
Depois, há a análise sintática. O Moment é flexível por natureza. Ele aceita entradas que bibliotecas mais rigorosas rejeitam de imediato ou interpretam de maneira diferente; e quando uma string não está em conformidade nem com a norma ISO 8601 nem com a RFC 2822, ele recorre ao formato nativo Date construtor, uma fonte clássica de erros do tipo “off-by-one-day”. Se você substituir por um analisador mais rigoroso, as entradas que antes “funcionavam” podem agora ser rejeitadas ou resultar em um dia diferente.
Dica de quem conhece: Os tokens de formato também não são portáteis. O Moment’s YYYY-MM-DD é yyyy-MM-dd no date-fns e no Luxon. O Day.js mantém os tokens do Moment, e o date-fns, pelo menos, gera uma exceção ao YYYY por padrão. O Luxon não lança nada. Ele não reconhece YYYY e o exibe literalmente, e DD significa uma data localizada naquele lugar, portanto YYYY-MM-DD fica mais ou menos assim: “YYYY-12-29 de dezembro de 2026”. Uma substituição automática em sequências de tokens é uma maneira bem documentada de gerar resultados incorretos sem que ninguém perceba, erros que nenhum compilador detectará.
Os fusos horários são ainda mais complicados. A hora local em relação ao UTC, as mudanças para o horário de verão e os dados históricos de fusos horários podem apresentar diferenças sutis entre as bibliotecas, e essas diferenças só se tornam evidentes em datas específicas. Os dados de localidade e os tokens de formato também variam, e nenhuma dessas diferenças causa erros evidentes.
É o modo de falha que torna isso perigoso. Seus testes são aprovados. A compilação está correta. Nada na integração contínua (CI) apresenta erros. Então, um relatório de fim de mês é divulgado com um dia de atraso, apenas para usuários em um fuso horário específico e apenas no limite desse fuso.
Imagine um produto de análise SaaS com cerca de 400 pontos de chamada do Moment distribuídos entre a configuração de gráficos, a exportação para CSV e os resumos programados por e-mail. Os gráficos e as exportações são executados constantemente, de modo que seus bugs são detectados rapidamente. Os resumos programados são executados uma vez por mês, formatam um intervalo de datas de acordo com o fuso horário do destinatário e, discretamente, enviam o intervalo incorreto a um subconjunto de clientes durante um ciclo de faturamento inteiro antes que alguém perceba. É assim que uma migração malsucedida do Moment se apresenta na prática.
Um plano de substituição baseado no comportamento
O plano que se mantém em uma base de código extensa é organizado em torno do comportamento, e não em torno de uma busca global pela sequência de caracteres moment. Ele deixa as partes arriscadas para o final, depois que você tiver certeza de que as partes fáceis deram certo.
Identifique primeiro todas as utilizações do Moment e do Moment Timezone, incluindo dependências transitivas e cópias incorporadas em pacotes de fornecedores ou bibliotecas de componentes. Em seguida, classifique cada ponto de chamada de acordo com o que ele realmente faz, seja análise sintática, formatação, operações aritméticas, localização ou operações relacionadas a fuso horário. Essas categorias apresentam riscos de migração muito diferentes, e agrupá-las em uma única categoria é o que leva as equipes a se depararem com surpresas.
Adicione testes de regressão com datas reais e casos extremos conhecidos antes de alterar uma única linha de código. As transições do horário de verão, os anos bissextos, as transições de fim de mês e os usuários fora do fuso horário UTC são os que causam problemas. Em seguida, canalize o tratamento de datas por meio de um módulo interno de datas, de modo que a biblioteca subjacente se torne um detalhe de implementação que você possa substituir por trás de uma interface estável, em vez de 400 chamadas diretas espalhadas pelo código. Esse wrapper é o padrão que realmente funciona.
Só então substitua os casos de uso restritos e de baixo risco, o que gera confiança e proporciona as ferramentas necessárias para os casos mais complexos. Acima de tudo, evite utilizar dois modelos de data no mesmo fluxo de trabalho de negócios sem uma delimitação explícita entre eles, pois a mistura de lógica mutável e imutável em um único fluxo é, por si só, uma fonte de erros.
Tomando uma decisão: Pouco espaço ocupado, cobertura de teste sólida e ausência de lógica de fuso horário? Migre agora. Uso intenso de fuso horário ou localidade? Faça o wrap primeiro e, depois, migre módulo por módulo. Um pacote congelado ou um componente de fornecedor que inclui o Moment? Atualize ou substitua a dependência quando a estrutura do pacote permitir e pare de tratar a remoção total como um item imediato do plano de ação.
Quando manter o Moment temporariamente é a decisão mais sensata
Às vezes, a resposta honesta é que você não vai realizar a migração neste trimestre, e essa pode ser a decisão correta. Pense em lógicas de datas regulamentadas ou financeiras, nas quais um erro de apenas um dia já constitui uma violação de conformidade; em grandes aplicativos internacionalizados cujo comportamento em diferentes configurações regionais não foi totalmente documentado; em produtos embarcados com longos ciclos de lançamento; ou em aplicativos sem cobertura de teste suficiente para validar uma migração apressada. Em todos esses casos, retirar o Moment sob pressão de tempo é a opção mais arriscada.
A ressalva é clara. “Temporariamente” precisa de um responsável, uma data e um registro. Sem esses três elementos, “temporário” significa apenas que a próxima auditoria vai constatar que aquilo ainda está lá.
É exatamente para essa lacuna que as atualizações oferecidas pelos fornecedores foram criadas. O ELS da TuxCare abrange moment 2.0.0, 2.10.6 e 2.24.0, além de moment-timezone 0.4.1, dentro de seu Cobertura de bibliotecas JavaScript. As correções são disponibilizadas por meio de npm com dados SBOM e VEX, de modo que a proveniência seja auditável. O Moment, por si só, não possui nenhuma dependência de tempo de execução; portanto, a questão da cobertura se concentra no Moment, e não em uma cadeia de pacotes subjacentes a ele.
A aplicação de patches de segurança continua na versão fixada enquanto seus testes de migração focados no comportamento avançam em um ritmo razoável, o que elimina a pressão de reescrever a lógica de datas dentro de um prazo definido por uma divulgação não relacionada. Você pode realizar a migração de acordo com sua programação, e não com o calendário das divulgações.
O papel do OpenJS na sustentabilidade
O Moment é hospedado pela OpenJS Foundation, que administra o Programa de Sustentabilidade do Ecossistema para que versões arquivadas, em fim de vida útil e mais antigas de seus projetos possam receber cobertura de segurança comercial, com uma parte dessa receita sendo revertida para os projetos. A TuxCare participa como membro Gold e provedora, e o programa é não exclusivo.
A melhor alternativa é aquela que você já comprovou
Os números de referência não vão te salvar no fim do mês. A melhor alternativa ao Moment.js é aquela cuja semântica você já comprovou em relação às datas em que sua empresa não pode se dar ao luxo de cometer erros.
