Outdated Date Library Can Be Used to Slow Down or Crash Your App

Your application is using an old version of Moment.js, a popular tool for handling dates and times. This version has a known weakness: if someone sends it a very long, specially crafted piece of text, it can cause your app to freeze or become unresponsive while it tries to process it. Think of it like a lock that jams when you insert a bent key — the door stops working for everyone until the jam clears.

Business Impact And Actions

medium urgency

Business Impact

If your app accepts date input from users (e.g. a booking form, date filter, or API field) and passes it directly to this library without checking its length first, a bad actor could deliberately slow down or temporarily knock out that part of your service. This could affect user experience and, depending on your setup, may flag as a known vulnerability in compliance or security audits.

What To Do

  1. Ask your developer to upgrade Moment.js to version 2.29.4 or later — or consider switching to a modern alternative like Day.js or date-fns, since Moment.js is no longer actively maintained.
  2. If an immediate upgrade isn't possible, ask your developer to add a simple check that rejects any date input longer than 200 characters before it reaches the library.
  3. Run a quick check to see if Moment.js is used in other parts of your codebase — the same fix applies everywhere it appears.
  4. Consider adding this type of library check to your regular maintenance routine so outdated dependencies are caught early.

Moment.js < 2.15.2 — Regular Expression Denial of Service (ReDoS) via duration() and date string parsing (CVE-2016-4055)

medium severity CVSS 5.3-6.5

Vulnerability Explanation

Moment.js versions prior to 2.15.2 contain inefficient regular expressions in the `moment.duration()` function and date string parsing routines. When a sufficiently long crafted string is passed as input, the regex engine enters catastrophic backtracking — a condition where processing time grows exponentially relative to input length. This can block the Node.js event loop for seconds or longer, making the application unresponsive to all other requests during that window. The attack requires no authentication and no special privileges — only the ability to submit input to any endpoint that passes user-supplied strings to Moment.js.

Root Cause

The vulnerable regular expressions use nested quantifiers and alternation patterns that allow the regex engine to explore an exponentially large number of matching paths when given adversarial input. Specifically, the `duration()` parser and the RFC2822 date string preprocessor did not anchor or bound their patterns, and did not validate input length before processing.

Technical Impact

An unauthenticated remote attacker can cause temporary denial of service by submitting a crafted long string (typically 10,000–50,000+ characters) to any endpoint that passes user input to `moment()`, `moment.duration()`, or related parsing functions. This blocks the Node.js event loop, degrading or halting service for all concurrent users until the regex completes or the process is restarted.

Severity Justification

CVSS Base score of 5.3 per IBM X-Force (CVE-2016-4055); some sources rate it up to 6.5. Network-accessible, no authentication required, no privileges needed, but impact is limited to availability (DoS) only — no confidentiality or integrity impact. Exploitability is conditional on user-supplied input reaching the vulnerable parsing functions without length validation.

Affected Components

  • Moment.js < 2.15.2 (CVE-2016-4055 — duration() ReDoS)
  • Moment.js < 2.19.3 (CVE-2017-18214 — date string parsing ReDoS)
  • Moment.js 2.18.0 – 2.29.3 (CVE-2022-31129 — RFC2822 preprocessor ReDoS)

Remediation Steps

  1. Upgrade Moment.js to version 2.29.4 or the latest available (2.30.1). Run: npm install moment@latest or yarn add moment@latest
  2. Given that Moment.js is now in maintenance-only mode with no active development, strongly consider migrating to a modern alternative: Day.js (API-compatible drop-in, ~2KB), date-fns (tree-shakeable, functional), or the native Temporal API (where supported).
  3. If an immediate upgrade is blocked by compatibility constraints, add an input length guard before any call to Moment.js parsing functions — reject or truncate strings exceeding 200 characters.
  4. After upgrading, run your existing test suite and spot-check any date formatting or parsing logic to confirm behaviour is unchanged across the version jump.
  5. Add Moment.js (or its replacement) to your dependency monitoring pipeline (e.g. npm audit, Dependabot, Snyk) to catch future advisories automatically.

Verification Steps

  1. Run npm list moment or yarn list moment to confirm the installed version is 2.29.4 or later.
  2. Run npm audit and verify no Moment.js advisories are reported.
  3. If migrating to Day.js or date-fns, run your full test suite and confirm all date-related functionality passes.
  4. Optionally, use a tool like retire.js or OWASP Dependency-Check in your CI pipeline to flag vulnerable library versions going forward.

Code Examples (javascript)

Vulnerable
const moment = require('moment');

// Vulnerable: user input passed directly without length check
app.post('/calculate-duration', (req, res) => {
  const duration = moment.duration(req.body.input); // ReDoS if input is very long
  res.json({ duration: duration.asSeconds() });
});
Fixed
// Option A: Upgrade and add input length guard (works with any version)
const moment = require('moment'); // ensure >= 2.29.4

app.post('/calculate-duration', (req, res) => {
  const input = req.body.input;
  if (typeof input !== 'string' || input.length > 200) {
    return res.status(400).json({ error: 'Invalid input' });
  }
  const duration = moment.duration(input);
  res.json({ duration: duration.asSeconds() });
});

// Option B: Migrate to Day.js (drop-in compatible for most use cases)
const dayjs = require('dayjs');
const duration = require('dayjs/plugin/duration');
dayjs.extend(duration);

app.post('/calculate-duration', (req, res) => {
  const input = req.body.input;
  if (typeof input !== 'string' || input.length > 200) {
    return res.status(400).json({ error: 'Invalid input' });
  }
  const d = dayjs.duration(input);
  res.json({ duration: d.asSeconds() });
});

Best Practices

  • Always validate and limit the length of user-supplied strings before passing them to any date/time parsing library — 200 characters is a safe upper bound for any legitimate date-time string.
  • Prefer actively maintained libraries; Moment.js has been in maintenance-only mode since 2020 and will not receive new security patches beyond critical fixes.
  • Integrate automated dependency scanning (npm audit, Dependabot, or Snyk) into your CI/CD pipeline to surface vulnerable library versions before they reach production.
  • Apply rate limiting on public API endpoints that perform CPU-intensive operations to reduce the blast radius of any ReDoS or DoS attempt.

Found this in your infrastructure?

VulWall scans for this and dozens of other issues automatically.

Scan Your Domain Free