From 6bf901a66dedea6b8ac5070831c5b843487d67ca Mon Sep 17 00:00:00 2001 From: SkyZeroZx <73321943+SkyZeroZx@users.noreply.github.com> Date: Sun, 14 Jun 2026 13:28:02 -0500 Subject: [PATCH] fix(core): avoid caching missing locale data Only cache locale data loaded from the global locale registry when an actual locale entry is found. This prevents attacker-controlled missing locale identifiers from being retained indefinitely in SSR when locale lookup falls back to a parent locale or the built-in English locale, avoiding unbounded process memory growth in locale-aware pipes and formatters. (cherry picked from commit ea8277ae37f57f0fb8977ce54ad8b83339106522) --- packages/core/src/i18n/locale_data_api.ts | 11 ++++++++++- packages/core/test/i18n/locale_data_api_spec.ts | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/core/src/i18n/locale_data_api.ts b/packages/core/src/i18n/locale_data_api.ts index 21bd136501a6..910a8e169ae5 100644 --- a/packages/core/src/i18n/locale_data_api.ts +++ b/packages/core/src/i18n/locale_data_api.ts @@ -102,11 +102,20 @@ export function getLocalePluralCase(locale: string): (value: number) => number { */ export function getLocaleData(normalizedLocale: string): any { if (!(normalizedLocale in LOCALE_DATA)) { - LOCALE_DATA[normalizedLocale] = + const globalLocaleData = global.ng && global.ng.common && global.ng.common.locales && global.ng.common.locales[normalizedLocale]; + // Only cache global locale data when an entry is actually found, to avoid + // caching missing lookups. In SSR this cache is process-wide across requests, + // so caching `undefined` would retain attacker-controlled locale identifiers + // indefinitely. It would also make the `in` check above short-circuit on + // subsequent lookups and skip the global fallback. + if (globalLocaleData !== undefined) { + LOCALE_DATA[normalizedLocale] = globalLocaleData; + } + return globalLocaleData; } return LOCALE_DATA[normalizedLocale]; } diff --git a/packages/core/test/i18n/locale_data_api_spec.ts b/packages/core/test/i18n/locale_data_api_spec.ts index e6367f8fa0cd..81be3955007d 100644 --- a/packages/core/test/i18n/locale_data_api_spec.ts +++ b/packages/core/test/i18n/locale_data_api_spec.ts @@ -85,6 +85,16 @@ describe('locale data api', () => { expect(findLocaleData('de-CH')).toEqual(localeDeCH); }); + it('should not cache missing global locale data lookups', () => { + const localeEnNZ: any[] = ['en-NZ']; + + expect(findLocaleData('en-NZ')).toEqual(localeEn); + + global.ng.common.locales['en-nz'] = localeEnNZ; + + expect(findLocaleData('en-NZ')).toBe(localeEnNZ); + }); + it('should find the parent LOCALE_DATA if the exact locale is not available and the parent locale is on the global object', () => { expect(findLocaleData('de-BE')).toEqual(localeDe); });