Skip to content

isRFC3339 accepts leap seconds at impossible instants #2863

Description

@uhop

Describe the bug

isRFC3339 allows the seconds value 60 at any hour and minute:

const timeSecond = /([0-5][0-9]|60)/;

RFC 3339 §5.6
allows 60 only for a leap second, and a leap second occurs only at 23:59:60
UTC. After the offset is applied, any other instant is unrepresentable.

I want to flag up front that '2009-05-31 14:53:60Z' is currently in the valid
list in test/validators.test.js, and that #2841 mentions keeping it valid. So
this is a question about intended strictness rather than a straightforward bug,
and it may well be deliberate.

Examples

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

// A real leap second: correct
validator.isRFC3339('2016-12-31T23:59:60Z'); // true

// Not a possible instant for a leap second
validator.isRFC3339('2020-01-01T00:00:60Z'); // true
validator.isRFC3339('2009-05-31T14:53:60Z'); // 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

If the leniency is intentional, it would help to say so in the docs, since
isRFC3339 is otherwise strict enough that callers may reasonably read a
true as "this is a representable instant". If it is not intentional, the
check is hour === 23 && minute === 59 guarding the 60 alternative, applied
after the offset.

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