mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(common): Limits date format string length
Introduces a maximum length of 256 characters for date format strings. This prevents potential Denial of Service (DoS) attacks by throwing an `INVALID_DATE_FORMAT` error if an excessively long format string is provided to `formatDate` or `DatePipe`, safeguarding against performance degradation or application crashes.
This commit is contained in:
@@ -36,6 +36,7 @@ export const ISO8601_DATE_REGEX =
|
||||
const NAMED_FORMATS: {[localeId: string]: {[format: string]: string}} = {};
|
||||
const DATE_FORMATS_SPLIT =
|
||||
/((?:[^BEGHLMOSWYZabcdhmswyz']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|Y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|c{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/;
|
||||
const MAX_DATE_FORMAT_LENGTH = 256;
|
||||
|
||||
const enum ZoneWidth {
|
||||
Short,
|
||||
@@ -89,6 +90,7 @@ export function formatDate(
|
||||
timezone?: string,
|
||||
): string {
|
||||
let date = toDate(value);
|
||||
assertValidDateFormatLength(format);
|
||||
const namedFormat = getNamedFormat(locale, format);
|
||||
format = namedFormat || format;
|
||||
|
||||
@@ -132,6 +134,16 @@ export function formatDate(
|
||||
return text;
|
||||
}
|
||||
|
||||
function assertValidDateFormatLength(format: string) {
|
||||
if (format.length > MAX_DATE_FORMAT_LENGTH) {
|
||||
throw new RuntimeError(
|
||||
RuntimeErrorCode.SUSPICIOUS_DATE_FORMAT,
|
||||
ngDevMode &&
|
||||
`Date format is too long. Exceeded maximum length of ${MAX_DATE_FORMAT_LENGTH} characters.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given date format is free from common mistakes. Throws an
|
||||
* error if one is found (except for the case of all "Y", in which case we just
|
||||
|
||||
@@ -351,6 +351,16 @@ describe('Format date', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw if the date format exceeds 256 characters to prevent DoS', () => {
|
||||
const expectedError = /Exceeded maximum length of 256 characters/;
|
||||
expect(() => formatDate(date, 'y'.repeat(257), ɵDEFAULT_LOCALE_ID)).toThrowError(
|
||||
expectedError,
|
||||
);
|
||||
expect(() => formatDate(date, "'literal'".repeat(257), ɵDEFAULT_LOCALE_ID)).toThrowError(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('should format invalid in IE ISO date', () =>
|
||||
expect(formatDate('2017-01-11T12:00:00.014-0500', defaultFormat, ɵDEFAULT_LOCALE_ID)).toEqual(
|
||||
'Jan 11, 2017',
|
||||
|
||||
@@ -77,6 +77,12 @@ describe('DatePipe', () => {
|
||||
it('should give precedence to the passed in format', () =>
|
||||
expect(pipe.transform('2017-01-11T10:14:39+0000', 'shortDate')).toEqual('1/11/17'));
|
||||
|
||||
it('should reject date formats that are too long', () => {
|
||||
expect(() => pipe.transform(date, 'y'.repeat(257))).toThrowError(
|
||||
/InvalidPipeArgument: 'NG02300: Date format is too long/,
|
||||
);
|
||||
});
|
||||
|
||||
it('should use format provided in component as default format when no format is passed in', () => {
|
||||
@Component({
|
||||
selector: 'test-component',
|
||||
|
||||
Reference in New Issue
Block a user