Skip to content

Security: ReDoS vulnerability in parse regex #291

@rkristelijn

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions