From 26831d0cbd7e692210ca0799a203a7a5a0e741cd 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 1/7] 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); }); From 8eb7aea08b27c0f1bcdeec3171880a6fcf28aa9a Mon Sep 17 00:00:00 2001 From: SkyZeroZx <73321943+SkyZeroZx@users.noreply.github.com> Date: Sun, 28 Jun 2026 00:15:56 -0500 Subject: [PATCH 2/7] fix(core): reject dynamic script host elements The previous fix for GHSA-692r-grfm-v8x7 was incomplete because it rejected script tags only when locating an explicit host element. Dynamic component instantiation can also infer the host element from the component selector. Move the script-host rejection to the point where ComponentFactory has resolved the host element for either path, so createComponent rejects script hosts consistently. (cherry picked from commit 135f3755b4a2c4920c2f056bfe224a7bc067bb83) --- packages/core/src/render3/component_ref.ts | 10 ++++++++++ packages/core/src/render3/instructions/shared.ts | 7 ------- packages/core/test/acceptance/security_spec.ts | 13 +++++++++++++ .../bundle.golden_symbols.json | 1 + .../test/bundling/defer/bundle.golden_symbols.json | 1 + .../forms_reactive/bundle.golden_symbols.json | 1 + .../bundle.golden_symbols.json | 1 + .../bundling/hydration/bundle.golden_symbols.json | 1 + .../test/bundling/router/bundle.golden_symbols.json | 1 + .../standalone_bootstrap/bundle.golden_symbols.json | 1 + 10 files changed, 30 insertions(+), 7 deletions(-) diff --git a/packages/core/src/render3/component_ref.ts b/packages/core/src/render3/component_ref.ts index 5cca900962ad..4baea34e9f6a 100644 --- a/packages/core/src/render3/component_ref.ts +++ b/packages/core/src/render3/component_ref.ts @@ -193,6 +193,15 @@ function createHostElement(componentDef: ComponentDef, renderer: Render return createElementNode(renderer, tagName, namespace); } +function assertNotScriptHostElement(tagName: string | null | undefined): void { + if (tagName?.toLowerCase() === 'script') { + throw new RuntimeError( + RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT, + ngDevMode && `"