Safeguard
Vulnerabilities

CVE-2022-31129: The Day.js ReDoS Vulnerability, Explained

CVE-2022-31129 is a regular expression denial of service in Day.js's custom parse format handling. Here's what triggered it, why it's still showing up in scans, and how it was fixed.

Safeguard Research Team
Research
5 min read

CVE-2022-31129 is a regular expression denial of service (ReDoS) vulnerability in Day.js, the lightweight date library many teams adopted specifically as a smaller alternative to Moment.js. The bug lives in the custom parse format handling, when Day.js parses a date string against a user-supplied format pattern, certain crafted input strings cause the underlying regular expression engine to take catastrophically long to evaluate, effectively locking up the event loop in a single-threaded Node.js process.

What was the vulnerable code path?

Day.js supports parsing dates against a custom format string, similar to Moment's moment(dateString, format) API:

dayjs(userSuppliedString, "YYYY-MM-DD HH:mm:ss")

Internally, versions of Day.js before the fix built a regular expression from the format string to match against the input, and that generated regex contained a pattern vulnerable to catastrophic backtracking under specific crafted inputs. Because JavaScript's regex engine is single-threaded and blocking, an input string engineered to maximize backtracking could pin the CPU on a single request, and enough concurrent requests hitting the vulnerable parse path could take down an entire Node.js process.

Why does this matter more than it sounds like it should?

Date parsing looks like a low-risk corner of an application, but ReDoS bugs in date and string-parsing libraries are dangerous precisely because the vulnerable code path is often reachable directly from unauthenticated user input, form fields, query parameters, API payloads that include a date string, with no additional exploitation complexity required. There's no need to chain the bug with anything else; a single crafted string sent to an endpoint that parses it with a vulnerable format is enough to cause a denial of service.

Day.js's popularity amplifies the blast radius. It was adopted widely as the lighter-weight Moment.js replacement, and by the time this CVE was disclosed it was already a dependency, often a transitive one, in a large number of Node.js and frontend projects. That's the recurring pattern with ReDoS in widely used utility libraries: the vulnerability itself is narrow, but the reach is enormous because so much code calls into it without anyone tracking that a date-parsing call is a potential denial-of-service surface.

How was CVE-2022-31129 actually fixed?

The maintainers patched the custom parse plugin to change how the format string was translated into a regular expression, removing the specific backtracking-prone construction. The fix shipped in Day.js 1.11.5. If you're running an older 1.11.x release, or anything before 1.11.5, and you use the customParseFormat plugin with user-controlled input, you're exposed. Projects that only use Day.js's default ISO-8601 parsing without the custom format plugin were not affected by this specific path, which is a useful distinction when triaging whether the CVE actually applies to your usage.

How do you check if you're affected?

Start with your lockfile. Running npm ls dayjs (or the equivalent for yarn or pnpm) will show you the resolved version and whether it's a direct or transitive dependency; transitive is the more common and more easily missed case, where a UI component library or a form validation package pulls in Day.js under the hood. Confirm the resolved version is 1.11.5 or later.

Beyond the version check, look at whether your code actually calls dayjs(input, format) with a format string, on input that comes from outside your trust boundary. If your only usage is parsing ISO date strings you generated yourself, the practical exploitability is much lower even on a vulnerable version, though upgrading costs nothing and removes the question entirely.

This is also a good example of why dependency scanning needs to go past "is this package listed as vulnerable" and toward reachability: a vulnerable version of Day.js sitting in node_modules because some unrelated package depends on it, without your code ever calling the vulnerable parse path with untrusted input, is a very different risk than the same version reachable from an internet-facing form. A software composition analysis tool that can distinguish those two cases saves a lot of unnecessary urgency.

FAQ

What CVSS score does CVE-2022-31129 carry?

It's generally tracked around CVSS 7.5 (High), reflecting the network-reachable, no-authentication-required denial-of-service impact, with no confidentiality or integrity loss since it's purely an availability bug.

Does upgrading Day.js break existing date-parsing behavior?

The 1.11.5 fix changed internal regex construction, not the public parsing API, so for the vast majority of projects the upgrade is a drop-in fix with no behavior change to valid, well-formed date inputs.

Are other date libraries vulnerable to the same class of bug?

Yes. ReDoS has appeared in Moment.js, and in various validation and parsing libraries across the JavaScript ecosystem, because hand-rolled regex-based parsers are a common source of catastrophic backtracking bugs. It's a pattern worth checking for in any library that builds regexes from configurable input.

How urgently should teams patch this?

Treat it as a standard high-priority dependency update if customParseFormat is used with untrusted input reachable from the network; there's no reason to delay given the trivial, drop-in fix and the low cost of testing a patch-level version bump.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.