Skip to content

isISO8601 misroutes signed ordinal dates #2860

Description

@uhop

Describe the bug

The ordinal-date branch in isValidDate matches with

const ordinalMatch = str.match(/^(\d{4})-?(\d{3})([ T]{1}\.*|$)/);

That pattern has no sign prefix, although the main isISO8601 regex accepts a
leading + or - on the year. A signed ordinal date therefore fails this
match and falls through to the calendar branch, where the generic
(\d{4})-?(\d{0,2})-?(\d*) split cuts the three-digit day-of-year into a
two-digit month and a one-digit day.

The result is that day-of-year is never validated for signed ordinal dates, and
some valid ones are rejected outright.

Examples

const validator = require('validator'); // 13.15.35

// Day 145 of 2009 exists, but the split reads month 14, day 5 and rejects it
validator.isISO8601('+2009-145', { strict: true }); // false, expected true

// Day 130 exists too; here the split reads month 13, day 0, the guard falls
// through, and it is accepted without any check
validator.isISO8601('+2009-130', { strict: true }); // true, unvalidated

// Unsigned ordinals take the intended branch and behave correctly
validator.isISO8601('2009-145', { strict: true });  // true

Reproductions

The Examples block above runs as-is on Node after
npm install validator@13.15.35; no harness or scaffolding needed.

Additional context

Adding [+-]? to the ordinal pattern would route these to the branch that
already handles them, including the leap-year bound on line 19.

Validator.js version: 13.15.35
Node.js version: v26.7.0
OS platform: Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions