CVE-2022-24785 is a path traversal vulnerability in Moment.js versions before 2.29.2: when a Node.js application passes user-controlled input into Moment's locale-switching APIs, input containing directory-traversal sequences can escape the library's bundled locale directory and cause the server to load an unintended JavaScript file from disk. It was disclosed in April 2022, carries a CVSS 3.1 score of 7.5 (High), and is fixed by upgrading to 2.29.2 or later — a change that sanitizes locale names before they touch the filesystem.
What is CVE-2022-24785?
Moment.js is one of the most downloaded date libraries in the npm ecosystem, embedded in countless applications directly and — more often — transitively. On Node.js, when code calls moment.locale(name) with a locale that is not yet loaded, the library resolves and loads a file from its bundled locale/ directory based on that name. Before 2.29.2, the locale string was not sanitized, so a value containing ../ sequences could point the resolution outside the locale directory entirely. The advisory (GHSA-8hfj-j24r-96c4) classifies it as path traversal (CWE-22, specifically the dir/../filename variant, CWE-27), affecting server-side npm users of the library.
How does the Moment.js path traversal work?
The vulnerable pattern is any server endpoint that lets the client pick a locale:
const moment = require("moment");
const express = require("express");
const app = express();
app.get("/dates", (req, res) => {
// Attacker-controlled value flows straight into locale resolution
moment.locale(req.query.locale);
res.send(moment().format("LLLL"));
});
With a benign value like fr, Moment loads its bundled French locale file. With a crafted value such as ../../../../some/path/on/disk, the pre-2.29.2 resolution logic builds a path that walks out of the locale directory, and Node's module loading machinery attempts to load whatever JavaScript file the traversal lands on. The practical impacts are loading files the application never intended to execute or expose, and denial of service — pointing resolution at a large or invalid target can hang or crash the process. NVD's scoring (network vector, no privileges, no user interaction, high confidentiality impact) reflects the file-exposure scenario.
The fix in 2.29.2 is small and instructive: locale names are sanitized before being used to build a path, so traversal characters can no longer influence resolution.
Who is actually exposed?
Exposure requires two conditions together: running Moment on Node.js (server-side), and passing untrusted input into locale APIs. Browser bundles are largely out of scope — bundlers like webpack statically include locale files at build time rather than resolving paths at runtime. This is a textbook case for reachability analysis: dependency scanners will flag every lockfile pinning an old Moment version, but the finding is urgent specifically where user input reaches moment.locale() or equivalent APIs on a server. That distinction should set your patch order — internet-facing services with dynamic locale switching first, build tooling last.
Because Moment appears transitively in so many dependency trees, most affected teams do not know they ship it. This is exactly what software composition analysis is for: enumerating every path in the graph that resolves to moment below 2.29.2, including copies nested under other packages.
How do you fix CVE-2022-24785?
Three steps, in order of durability:
- Upgrade to at least
2.29.2— but in practice go straight to2.29.4or later, because2.29.4also fixes CVE-2022-31129, a ReDoS in Moment's string parsing disclosed a few months later. One upgrade, two advisories closed. - Allowlist locales regardless. Even on a patched version, mapping user input through an explicit set (
["en", "fr", "de"]and so on) is cheap defense in depth and better product behavior than accepting arbitrary strings. - Plan the exit. Moment.js has been in maintenance mode since 2020; its own maintainers recommend evaluating alternatives such as Luxon, Day.js, or date-fns for new work. You do not need an emergency migration for this CVE, but every quarter Moment stays in the tree is another future advisory you will be triaging.
For transitive copies you cannot upgrade directly, npm overrides (or Yarn resolutions) force the patched version tree-wide while you wait for upstream maintainers to bump their ranges. If you are comparing how scanning platforms handle this kind of override-based remediation, our Snyk comparison walks through the differences.
FAQ
Is CVE-2022-24785 exploitable in the browser?
Effectively no. The traversal happens in server-side locale file resolution; browser builds ship with locales bundled statically, so there is no runtime path resolution to abuse. Scanners will still flag the version, so record the reasoning when you deprioritize front-end-only usage.
Which Moment.js version fixes CVE-2022-24785?
Version 2.29.2, released in April 2022. The pragmatic target is 2.29.4 or newer, which also resolves the CVE-2022-31129 ReDoS. Both are drop-in patch releases with no API changes.
Should we remove Moment.js entirely?
Eventually, for new code — the project is in maintenance mode and modern alternatives are smaller and actively developed. But removal is a refactor, not a security hotfix. Patch first, allowlist locales, then migrate on a normal engineering timeline.
How do I find every copy of Moment in my organization?
Search lockfiles for moment entries below the fixed version, including nested and transitive instances — or let an SCA tool do it continuously across every repository, which also catches the copy that arrives next month inside a new dependency.