From 3001b3a9855a43deec9f812f5e552f66e1f6aa8b Mon Sep 17 00:00:00 2001 From: yu2971512385-ui <287936273+yu2971512385-ui@users.noreply.github.com> Date: Thu, 17 Sep 2026 10:45:44 +0800 Subject: [PATCH] fix(isISO8601): only accept T or a space as the date-time separator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default pattern separated the date and time with `[T\s]`, so tab, newline, form feed, vertical tab and a non-breaking space were all accepted as separators. ISO 8601 permits only `T`, and RFC 3339 §5.6 additionally allows a plain space — no specification allows the rest of `\s`. Accepting a newline is particularly undesirable since it lets a two-line input pass a single-value check. Narrow the class to `[T ]`. `strictSeparator: true` (which already uses `[T]`) is unchanged. Fixes #2861 Co-Authored-By: Claude Opus 4.8 (1M context) --- src/lib/isISO8601.js | 2 +- test/validators.test.js | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/lib/isISO8601.js b/src/lib/isISO8601.js index 6eea9ae27..873aec756 100644 --- a/src/lib/isISO8601.js +++ b/src/lib/isISO8601.js @@ -2,7 +2,7 @@ import assertString from './util/assertString'; /* eslint-disable max-len */ // from http://goo.gl/0ejHHW -const iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W(0[1-9]|[1-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[0-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/; +const iso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W(0[1-9]|[1-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[0-6])))([T ]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/; // same as above, except with a strict 'T' separator between date and time const iso8601StrictSeparator = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W(0[1-9]|[1-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[0-6])))([T]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/; /* eslint-enable max-len */ diff --git a/test/validators.test.js b/test/validators.test.js index 98d2a12ff..4c24efb41 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -12420,6 +12420,23 @@ describe('Validators', () => { }); }); + it('should only accept T or a space as the date-time separator', () => { + test({ + validator: 'isISO8601', + valid: [ + '2009-01-01T00:00:00', + '2009-01-01 00:00:00', + ], + invalid: [ + '2009-01-01\t00:00:00', + '2009-01-01\n00:00:00', + '2009-01-01\f00:00:00', + '2009-01-01\v00:00:00', + '2009-01-01 00:00:00', + ], + }); + }); + it('should validate ISO 8601 dates, with strict = true (regression)', () => { test({ validator: 'isISO8601',