Skip to content

Security: ReDoS vulnerability in parse regex #291

Description

@rkristelijn

Summary

The regex in parse() is vulnerable to catastrophic backtracking (ReDoS) when given long numeric input followed by an invalid unit.

Proof of Concept

const ms = require("ms");

const start = performance.now();
ms("9".repeat(1000) + "z");
console.log(performance.now() - start); // ~4.2ms per call

In comparison, valid input of the same length:

ms("9".repeat(1000)); // ~0.001ms (matches immediately)

Impact

A server parsing user-supplied time strings (cache headers, rate limit config, timeout values) can be CPU-exhausted by sending many malicious inputs. Each call takes ~4ms, so 250 concurrent requests = 1 second of blocked event loop.

CVSS: Low (requires user input reaching the parse function)
CWE: CWE-1333 (Inefficient Regular Expression Complexity)

Root Cause

The regex (-?\d*\.?\d+) has ambiguity between \d* and \d+ — the engine tries all possible splits when the overall match fails.

Suggested Fix

Add input length validation before regex execution:

function parse(str) {
  str = String(str);
  if (str.length > 100) return; // no valid time string is >100 chars
  // ... existing regex logic
}

This is the approach we implemented in @flupkejs/ms.

Environment

  • ms version: 2.1.3 (latest)
  • Node.js: v22+
  • Tested: 2026-05-25

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions